Express: Using Passport to authenticate using a session - express

I am using Express 4 with Node.js - I have successfully implemented Passport to authenticate with a username/password. But how do I get Passport to authenticate with just session information?
How would I create a custom Passport strategy to take the session info and compare it with a particular user's info?
I am looking for this:
passport.use(new SessionStrategy(function(req,res,done){
if(req.session blah blah blah){
???
}
});
);
I really have no idea what the best way to do this is. Perhaps I store the user's latest session information on the backend-database. So instead of finding a user with their username, I find a user with the sessionid?
One answer seems to be the following:
This is the code to put the session-id into a cookie and retrieve the data when the user comes back. No strategy required.
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});

You have two options :
Use persistent session store
JSON Web Token
For implementing persistent session, you can use MongoDB session store or Redis Session store.
If you want to use redis then make use of connect-redis npm package. If you want to use MongoDb as session store then make use of connect-mongo npm package
There are some settings which you need to do in you app.js/server.js. In one of my demo i am using Redis Session store with PassportJS, if you are looking for example, feel free to look here.
If you want to use JSON web tokens, there are many different implementations available. I am using jsonwebtoken. I implemented this using PassportJS, ExpressJS and AngularJS in front End. For example look here. Tokens are encoded and stored in browser's local storage with a secret key.
I would suggest you to go for JSON web tokens, read it in detail because that is how most of the major web apps are developed.
Both of my examples are working prototype. Let me know if you need more help.

The ideal way to do this is to store a user ID in the session (or a JWT as #NarendraSoni mentioned). The main idea is to store as little useful information as possible in the session, as you should treat it like it's publicly available to everyone.
If you do store just a user ID, for instance, then each time you receive a request (req.session.userId, for instance), you could simple execute a database query to retrieve that user by the ID.
This is fast (especially if you use a server-side cache like memcached or redis), and causes very little latency. It's also secure, and prevents leaking user information to the browser.
If you're looking for a simpler way to handle this stuff in your app, you might want to check out my authentication library: express-stormpath. It does all of this stuff out of the box, is very secure, and provides lots of helper utilities to get you going faster: you can store custom data in accounts (like mongo), you can restrict users based on permissions, you can do API authentication, etc.

Related

Is it okay to use Firebase Auth SDK for Mobile app authentication on the frontend? [duplicate]

The Firebase Web-App guide states I should put the given apiKey in my Html to initialize Firebase:
// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: '<your-api-key>',
authDomain: '<your-auth-domain>',
databaseURL: '<your-database-url>',
storageBucket: '<your-storage-bucket>'
};
firebase.initializeApp(config);
</script>
By doing so, the apiKey is exposed to every visitor.
What is the purpose of that key and is it really meant to be public?
The apiKey in this configuration snippet just identifies your Firebase project on the Google servers. It is not a security risk for someone to know it. In fact, it is necessary for them to know it, in order for them to interact with your Firebase project. This same configuration data is also included in every iOS and Android app that uses Firebase as its backend.
In that sense it is very similar to the database URL that identifies the back-end database associated with your project in the same snippet: https://<app-id>.firebaseio.com. See this question on why this is not a security risk: How to restrict Firebase data modification?, including the use of Firebase's server side security rules to ensure only authorized users can access the backend services.
If you want to learn how to secure all data access to your Firebase backend services is authorized, read up on the documentation on Firebase security rules. These rules control access to file storage and database access, and are enforced on the Firebase servers. So no matter if it's your code, or somebody else's code that uses you configuration data, it can only do what the security rules allow it to do.
For another explanation of what Firebase uses these values for, and for which of them you can set quotas, see the Firebase documentation on using and managing API keys.
If you'd like to reduce the risk of committing this configuration data to version control, consider using the SDK auto-configuration of Firebase Hosting. While the keys will still end up in the browser in the same format, they won't be hard-coded into your code anymore with that.
Update (May 2021): Thanks to the new feature called Firebase App Check, it is now actually possible to limit access to the backend services in your Firebase project to only those coming from iOS, Android and Web apps that are registered in that specific project.
You'll typically want to combine this with the user authentication based security described above, so that you have another shield against abusive users that do use your app.
By combining App Check with security rules you have both broad protection against abuse, and fine gained control over what data each user can access, while still allowing direct access to the database from your client-side application code.
Building on the answers of prufrofro and Frank van Puffelen here, I put together this setup that doesn't prevent scraping, but can make it slightly harder to use your API key.
Warning: To get your data, even with this method, one can for example simply open the JS console in Chrome and type:
firebase.database().ref("/get/all/the/data").once("value", function (data) {
console.log(data.val());
});
Only the database security rules can protect your data.
Nevertheless, I restricted my production API key use to my domain name like this:
https://console.developers.google.com/apis
Select your Firebase project
Credentials
Under API keys, pick your Browser key. It should look like this: "Browser key (auto created by Google Service)"
In "Accept requests from these
HTTP referrers (web sites)", add the URL of your app (exemple: projectname.firebaseapp.com/* )
Now the app will only work on this specific domain name. So I created another API Key that will be private for localhost developement.
Click Create credentials > API Key
By default, as mentioned by Emmanuel Campos, Firebase only whitelists localhost and your Firebase hosting domain.
In order to make sure I don't publish the wrong API key by mistake, I use one of the following methods to automatically use the more restricted one in production.
Setup for Create-React-App
In /env.development:
REACT_APP_API_KEY=###dev-key###
In /env.production:
REACT_APP_API_KEY=###public-key###
In /src/index.js
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
// ...
};
I am not convinced to expose security/config keys to client. I would not call it secure, not because some one can steal all private information from first day, because someone can make excessive request, and drain your quota and make you owe to Google a lot of money.
You need to think about many concepts from restricting people not to access where they are not supposed to be, DOS attacks etc.
I would more prefer the client first will hit to your web server, there you put what ever first hand firewall, captcha , cloudflare, custom security in between the client and server, or between server and firebase and you are good to go. At least you can first stop suspect activity before it reaches to firebase. You will have much more flexibility.
I only see one good usage scenario for using client based config for internal usages. For example, you have internal domain, and you are pretty sure outsiders cannot access there, so you can setup environment like browser -> firebase type.
The API key exposure creates a vulnerability when user/password sign up is enabled. There is an open API endpoint that takes the API key and allows anyone to create a new user account. They then can use this new account to log in to your Firebase Auth protected app or use the SDK to auth with user/pass and run queries.
I've reported this to Google but they say it's working as intended.
If you can't disable user/password accounts you should do the following:
Create a cloud function to auto disable new users onCreate and create a new DB entry to manage their access.
Ex: MyUsers/{userId}/Access: 0
exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);
Update your rules to only allow reads for users with access > 1.
On the off chance the listener function doesn't disable the account fast enough then the read rules will prevent them from reading any data.
I believe once database rules are written accurately, it will be enough to protect your data. Moreover, there are guidelines that one can follow to structure your database accordingly. For example, making a UID node under users, and putting all under information under it. After that, you will need to implement a simple database rule as below
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
No other user will be able to read other users' data, moreover, domain policy will restrict requests coming from other domains.
One can read more about it on
Firebase Security rules
While the original question was answered (that the api key can be exposed - the protection of the data must be set from the DB rulles), I was also looking for a solution to restrict the access to specific parts of the DB.
So after reading this and some personal research about the possibilities, I came up with a slightly different approach to restrict data usage for unauthorised users:
I save my users in my DB too, under the same uid (and save the profile data in there). So i just set the db rules like this:
".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"
This way only a previous saved user can add new users in the DB so there is no way anyone without an account can do operations on DB.
Also adding new users is posible only if the user has a special role and edit only by admin or by that user itself (something like this):
"userdata": {
"$userId": {
".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
...
EXPOSURE OF API KEYS ISN'T A SECURITY RISK BUT ANYONE CAN PUT YOUR CREDENTIALS ON THEIR SITE.
Open api keys leads to attacks that can use a lot resources at firebase that will definitely cost your hard money.
You can always restrict you firebase project keys to domains / IP's.
https://console.cloud.google.com/apis/credentials/key
select your project Id and key and restrict it to Your Android/iOs/web App.
It is oky to include them, and special care is required only for Firebase ML or when using Firebase Authentication
API keys for Firebase are different from typical API keys:
Unlike how API keys are typically used, API keys for Firebase services are not used to control access to backend resources; that can only be done with Firebase Security Rules. Usually, you need to fastidiously guard API keys (for example, by using a vault service or setting the keys as environment variables); however, API keys for Firebase services are ok to include in code or checked-in config files.
Although API keys for Firebase services are safe to include in code, there are a few specific cases when you should enforce limits for your API key; for example, if you're using Firebase ML or using Firebase Authentication with the email/password sign-in method. Learn more about these cases later on this page.
For more informations, check the offical docs
I am making a blog website on github pages. I got an idea to embbed comments in the end of every blog page. I understand how firebase get and gives you data.
I have tested many times with project and even using console. I am totally disagree the saying vlit is vulnerable.
Believe me there is no issue of showing your api key publically if you have followed privacy steps recommend by firebase.
Go to https://console.developers.google.com/apis
and perfrom a security steup.
You should not expose this info. in public, specially api keys.
It may lead to a privacy leak.
Before making the website public you should hide it. You can do it in 2 or more ways
Complex coding/hiding
Simply put firebase SDK codes at bottom of your website or app thus firebase automatically does all works. you don't need to put API keys anywhere

Auth0: Specific questions about token storage and flow for mobile app

I’m building a react native app that will interact with APIs that I also write/manage. I have found Auth0 documentation for implementing this flow, but I’m not sure on where/when to save the tokens. I want to be sure I nail this step, because I feel like it has the potential to reduce the security of the flow by a great deal if I don’t do it correctly.
Here is the flow as I understand it (no error handling, only happy-path for sake of brevity):
A user enters the app for the first time, or is not already logged in
They log in using the Auth0 web-login-thingy
I receive a token
I can use the token to authenticate with my API
Questions:
Do I store that token? I don’t want my users to have to log in every time they use the app. If I do store the token, where do I store it?
If I’m not storing it, what do I do? Do I ping an authentication/authorization endpoint with Auth0 every time they open the app and get a new token?
Say I am storing the tokens, if I'm using the ID token for user data, should I be hitting the API again regularly to keep it up to date? Only when the user opens the app again? Not until they trigger a change in the app?
Instead of using the ID token for user data, should I just use that to get the user's ID and ping my database for user data?
I have the basics of this flow, and I'm able to sandbox it, but I want to start applying production-ready app logic to this flow and that's where I'm stuck. I’m a little lost here, so any help is good help.
Thanks!!
Here's a brief answer to your questions when using Auth0:
Yes! you store it, the most secure way to store the token is in your device's local storage, that way it is not kept either in application's state or in a global variable.
2&3. See above, but to add more information, you can configure your tokens to have an expiry length. in theory you would convert this 'expiry time from inception' to a date object, and can do one of two things; you can request a new token using the Refresh Token (that comes with the original) once the expiry has been reached, or force the user to re-log in and re issue a new token at this time (i prefer the latter, prevents people from just renewing their tokens forever as long as they remain logged in)
Use the auth token to request user information after login, this can be stored in app state/global variables/wherever. You then want to use the auth token in the Authorization Header for each API call, along with whatever data you are sending. this ensures that even once someone is INSIDE the application, they need to have a valid token to actually do anything involving data (imagine someone back-dooring into your app and skipping the authorization, or using something like postman to just hammer your API with garbage). it would work something like this: GET userData { Header: auth token } -> GET userProfile (by sending your user ID returned from GET userData) PLUS {Header: auth token }
I can give more in depth examples if you wish, and i apologize if i misunderstood any of the question and gave redundant/incorrect answers
Edit: Resources about using secure storage for keys
Document for when to use in-memory storage Vs persistent storage. The TL;DR is use in-memory if the key is expected to expire before a standard session duration, and persistent for storing a key between sessions
https://hackernoon.com/mobile-api-security-techniques-682a5da4fe10
link to Keychain Services doc
https://developer.apple.com/documentation/security/keychain_services#//apple_ref/doc/uid/TP30000897-CH203-TP1
link to SharedPreferences doc
https://developer.android.com/reference/android/content/SharedPreferences.html
AsyncStorage is a simple, unencrypted, asynchronous, persistent,
key-value storage system that is global to the app. [1]
You could store it in your AsyncStorage, but thats not necessarily a secure location itself (e.g. not encrypted, accessible on rooted devices...). Typically clients will issue access tokens that last anywhere from several hours to a couple days and these will provide their owner access to your API-resources. If there is sensitive data behind your login screen, you're probably better off simply re-doing the auth-flow and invalidate older access tokens on login.

Authentication with JWT using GraphQL

After some search on the web I found that the best way of JWT authentication when using GraphQL is by inserting the JWT token into the GraphQL context. By doing so, resolvers can have access to it and check if the user is logged in, has permissions, etc.
I was wondering if I will need to place the authentication logic/function into every resolver that authentication is required. Is there a way which I could set by default (eg. middlewares) the authentication to every query except for login/logout/register/forgotpasword ones?
This question pops up every so often but not enough has been discussed. I think the answer lies not in the technology but in which way best suits your needs.
It is important to be mindful when adopting GraphQL that;
You don't have to give up on REST
You can have more than one GraphQL endpoints
Here are some suggestions based on my experience with implementing GraphQL
Authentication
For login/logout/forgot password and the whole shebang, consider going old-school. Form Post + Server-side rendering, REST API served us well for decades. Many third-party authentication services are based on this (Facebook Login, Google, OAuth2... etc). I tend to avoid using GraphQL for this purpose.
Authorisation
The logic to check if the requester is authorised to access the GraphQL can be generalised to 2 levels
GraphQL services
Essentially you check to see if the requester is authorised to use GraphQL service. Typically it's easier to check if the requester is authenticated, else deny access to the service altogether. This is typically done via a web server middleware.
There will be times where you'll need to expose some GraphQL queries to anonymous users, and I tend to lean towards having another 'unrestricted' GraphQL endpoint. This endpoint tends to have little to no mutations, exposes a limited subset of information and restricted nested queries.
Basically, you look at the data and decide which information/operation is public and which is not. IMO this is much easier to manage and secure than have a single GraphQL endpoint and implementing authorisation checkpoints in every query path/resolver.
Fine grain authorisation
At this stage basically, all requesters are authenticated users. We may need to question:
Is the requester the same user whose info is currently viewed?
Is the requester a friend of the user whose info is currently viewed?
Is the requester a member of the company whose info is currently viewed?
This is where putting the checking logic in resolvers (or models) really makes sense. I personally think resolvers are a great place to do this. Coupled with DataLoader the implementation can still be fast and effective.
Hope this helps!
No need to do checking in resolvers. You can add a middleware in your server side.
const graphQLServer = express();
graphQLServer.use('/graphql', function(req, res, next) {
var token = req.headers.token;
if (token != null && token != 'undefined') {
//Do token verification here
next();
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
})
Just try this

Is Firebase's built-in authentication able to be used on a 3rd party server?

I'm looking to create a game server backend for a game I'm creating. We're currently using Firebase for handling of data and ads, and Firebase has built in authentication. Is it possible to have a user log into our app via Firebase's auth system, then confirm the user's authentication when they connect to the game server to ensure it's who they say they are?
Basically, after someone logs into our firebase, can we use that authentication information for a separate server, and what protocol/method would need to be used (if there's a specific one)
I've figured out the two steps you need to get the information required to auth, one clientside and one serverside. Note: the following examples are for the Java apis, but you can use any of firebase's equivalents.
Clientside: In the Firebase-Auth package, there's the FirebaseUser object. This contains information about their auth state, unique details, etc. There is a method here called getToken(), which will grab your token for the current authentication. Once you have this, you want to send it to the server when you need to auth.
Serverside: On the server, there's a FirebaseAuth object. Once you get the token from the client, you can use verifyIdToken(), which will confirm this is a valid token and give you the details about the user when you get the result. I suggest cross-checking the UUID against one a client sends, to just confirm someone didn't get their hands on a token and send a random ID.
Hope this helps.

What's the simplest way to do authentication with a web API?

I've got a web API that provides data to users without authentication (the website lets users post data, after they've logged in using traditional cookies & sessions). Someone wants to develop an iPhone app that adds things to my database, so I want a user to authenticate on the iPhone, and then the api will allow posting.
So, what should I look in to do this easily? The API as it stands is RESTful, it'd be nice to keep it that way. Obviously I'm new to this but there seem to be so many standards I don't know where to start. If I can code it up in less than an hour, that'd be ideal.
Much appreciated!
A decent way to implement this would be to provide the app creator with a token as well as an app id, and have them use that token as salt for an agreed upon encryption method to send username and password (plus app id) to a new API call for a new session.
Upon receiving the request for a new session, you would look up their token based on the appid provided, and try and decrypt the user/pass using the token.
If the user/pass are accepted, then you create a new session and return the session id to them, which they can send along with any new requests.
This prevents the app from having to send authentication for every request, and allows you to expire sessions at a given time.
WebSecurity was introduced in ASP.NET MVC 4. It relies on the SimpleMembershipProvider. It uses FormsAuthentication to manage cookies
WebMatrix.WebData.WebSecurity is provides security and authentication features for ASP.NET Web Pages applications, including the ability to create user accounts, log users in and out, reset or change passwords, and perform related tasks.
You must create or initialize an WebSecurity database before you can use the WebSecurity object in your code.
In the root of your web, create a page (or edit the page ) named _AppStart.cshtml.
_AppStart.cshtml
#{
WebSecurity.InitializeDatabaseConnection("Users", "UserProfile", "UserId", "Email", true);
}
you can authenticate your request by following code.
WebSecurity.Login(LoginName, Password, true)
once authenticated successed , you will get value of WebSecurity.IsAuthenticated is true and you will get user's identity
you can also use "SimpleRoleProvider" for manage roles in your application