Selenium WebDriver: Login to a website - node.js

Is there a way to login to a website without writing the actual password in the code. For example, I created a function to login:
var isAlreadyLogIn = false;
function LogIn (userId, password) {
if (!isAlreadyLogIn) {
driver.findElement(By.xpath("//*[#id='Email']")).sendKeys(userId);
driver.findElement(By.xpath("//*[#id='Password']")).sendKeys(password);
driver.findElement(By.xpath("//input[#value='Login']")).click();
isAlreadyLogIn = true;
}
}
it('Should login', function(done) {
LogIn("username", "password");
});

Your code will need access to the credentials. I think the most common way to solve this is to put the credentials into a config file and read it from there. If you don't want the passwords to be included with the code you can just not commit in the config-file to the repository, but share it with a different means. Alternatively you could pass the username and password as command-line arguments to your tests.
Here are NodeJS examples how to store the credentials in different ways. The examples are for databases, but the idea is the same.

One option is to use environment variables to store the username and password. This is what is recommended by SauceLabs. They have a best practices page that contains more details on how to create the environment variables, etc.
https://wiki.saucelabs.com/display/DOCS/Best+Practice%3A+Use+Environment+Variables+for+Authentication+Credentials

If you are using maven, an option is using the profiles and the override system properties.
<profile>
<id>QA</id>
<properties>
<runUrl>http://qaenvironment.com </runUrl>
<admin.username>admin</admin.username>
<admin.password>adminpass</admin.password>
<noadmin.username>noadmin</noadmin.username>
<noadmin.password>qwerty123</noadmin.password>
</properties>
</profile>
Runing the execution whit the QA profile, for example, and in the Java code using that:
driver.findElement(By.xpath("//*[#id='Email']")).sendKeys(System.getProperty("admin.username"));
driver.findElement(By.xpath("//*[#id='Password']")).sendKeys(System.getProperty("admin.password"));

Related

How to authenticate without writing credentials in the actual code? [duplicate]

As you may see, I have my db connection file and another "protected" file, where my credentials are, and this file is included in .gitignore. I import it and reach the data. Quite basic. Therefore my questions are:
Is this the right way to do it?
If not, how should I do it? Plus: how could I add extra security to my account,connection?
Let's suppose I have a private collection, that no one should see, how could I protect specially this collection? I mean, with a password or a two step verification let's say.
Current code:
const mongoose = require("mongoose");
const mongoCredentials = require("../protected/mongoCredential");
const URI = `mongodb+srv://${mongoCredentials.username}:${mongoCredential.password}
#firstcluster-eldi8.mongodb.net/culturapp?retryWrites=true&w=majority`;
mongoose.connect(URI, { useUnifiedTopology: true, useNewUrlParser: true })
.then(db => console.log("MongoDB is connected"))
.catch(err => console.log(">> ERROR: ",err));
module.exports = mongoose;
...I have my db connection file and another "protected" file, where my credentials are, and this file is included in .gitignore. I import it and reach the data..
The correct way to do it is to use envrironmental variables.
Use environmental variables
Environmental variables are set on the environment, i.e your local development machine or the remote production server.
Then, within your app, you read the environment variables and use them appropriately.
There's (at least) a couple reasons it's usually done like this:
The credentials don't exist in a file that can be read by someone viewing the repository contents. Someone cloning the repository doesn't need to know your database credentials.
The credentials are likely different between environments. You are likely using a different database on your local development machine and a different database in your remote production server.
Here's how you set environment variables (this is for Linux, other OS's might be different):
$ export MONGO_DB_USERNAME=foo
$ export MONGO_DB_PASSWORD=bar
and here's how you read them within Node.js:
console.log(process.env.MONGO_DB_USERNAME) // logs 'foo'
console.log(process.env.MONGO_DB_PASSWORD) // logs 'bar'
or pass variables to the process when starting up
Alternatively, you can pass variables when starting up the process like so:
$ MONGO_DB_USERNAME=foo MONGO_DB_PASSWORD=bar node app.js
However that's generally discouraged since you're most probably starting your process through the npm start script. Since package.json, where the npm start command is defined, is always committed to the repository it defeats the whole purpose of hiding the credentials.
Like you mentioned along lines, using environment variables is more like security through obfuscation.
I would try to have the credentials in a separate configuration file. With a bit of design, encrypt this file and store those keys in secure enclaves or TPMs.
Check this thread.

Using environment variables in Karate DSL testing

I'd like to incorporate GitLab CI into my Karate testing. I'd like to loop through my tests with different user names and passwords to ensure our API endpoints are responding correctly to different users.
With that in mind, I'd like to be able to store the usernames and passwords as secure environment variables in GitLab (rather than in the karate-config as plain text) and have Karate pull them as needed from either the karate-config or the feature files.
Looking through the docs and StackOverflow questions, I haven't seen an example where it's being done.
Updating with new information
In regards to Peter's comment below, which is what I need I am trying to set it up as follows:
set client id in karate-config:
var client_id = java.lang.System.getenv('client_id');
in the actual config object:
clientId: client_id
In my feature file tried to access it:
* def client_id = clientId
It still comes through as null, unfortunately.
You can read environment variables in karate using karate.properties,
eg,
karate.properties['java.home']
If this helps you to read the environment variables that you are keeping securely on your gitlab, then you can use it in your karate-config for authentication.
But your config and environment variable will look cumbersome if you are having too many users.
If you want to run a few features with multiple users, I would suggest you look into this post,
Can we loop feature files and execute using multiple login users in karate
EDIT:
Using java interop as suggested by peter:
var systemPath = java.lang.System.getenv('PATH');
to see which are all variables are actually exposed try,
var evars= java.lang.System.getenv();
karate.log(evars);
and see the list of all environment variables.

NodeJS and storing OAuth credentials, outside of the code base?

I am creating a NodeJS API server that will be delegatiing authentication to an oauth2 server. While I could store the key and secret along with the source code, I want to avoid doing that since it feels like a security risk and it is something that doesn't match the lifespan of a server implementation update (key/secret refresh will likely happen more often).
I could store it in a database or a maybe a transient json file, but I would like to know what are the considered the best practices in the NodeJS world or what is considered acceptable. Any suggestions are appreciated.
One option would be to set environment variables as part of your deployment and then access them in the code from the global process object:
var clientId = process.env.CLIENT_ID
var clientSecret = process.env.CLIENT_SECRET
Since I wanted to provide something that can store multiple values, I just created a JSON file and then read that into a module I called keystore (using ES6 class):
class KeyStore {
load() {
// load the json file from a location specified in the config
// or process.env.MYSERVER_KEYSTORE
}
get (keyname) {
// return the key I am looking for
}
}
module.exports = new KeyStore();
I would ideally want to store the file encrypted, but for now I am just storing it read only to the current user in the home directory.
If there is another way, that is considered 'better', then I am open to that.

Custom SonarQube admin user ussing puppet

I'm trying to config a SonarQube server using puppet.
My puppet manifests install software, deploy my custom sonar.properties, deploy ssl certificates, download and configure few plugins and, at last, start service.
The goal is config and reconfig SonarQube in automatic way.
During my postconfig step, I launch a puppet exec whith this SQL to set my own password form admin user.
"UPDATE users SET crypted_password='***********************************', salt='*******************************' where login='admin'
How I can calculate crypted_password and salt values for my password? (nowadays i use a fake sonar to change admin pass and look the value in db)
In pseudo code some like this...
crypted_password=crypt('pass')
Where crypt is
funcion crypt (anypass)
{
........
}
Thanks.
In the sonar-server's ruby source there is a ruby file for authentication by password: by_password.rb. Here you can see how Sonar encrypts passwords:
def password_digest(password, salt)
digest = REST_AUTH_SITE_KEY
REST_AUTH_DIGEST_STRETCHES.times do
digest = secure_digest(digest, salt, password, REST_AUTH_SITE_KEY)
end
digest
end
secure_digest is defined as:
def secure_digest(*args)
Digest::SHA1.hexdigest(args.flatten.join('--'))
end
So the encrypted password is the SHA1 of digest--salt--password--REST_AUTH_SITE_KEY repeated REST_AUTH_DIGEST_STRETCHES times. The values of REST_AUTH_SITE_KEY and REST_AUTH_DIGEST_STRETCHES are set in /web/WEB-INF/config/initializers/site_keys.rb and are empty string and 1 by default.
This is one way of achieving your goal. In my opinion a much better way is by creating a user via Sonar's REST API. However unfortunately it doesn't seem possible at the time (v4.1.2) to add a user to a group via the REST API.

Can I or Should I use a Global variable in Angularjs to store a logged in user?

I'm new to angular and developing my first 'real' application. I'm trying to build a calendar/scheduling app ( source code can all be seen on github ) and I want to be able to change the content if there is a user logged in (i.e. display details relevant to them) but here's the catch:
I don't want the app to be dependent on having a logged in user ( needs to be something that can be configured to work publicly, privately or both)
I don't want to implement the user/login within this app if it can be avoided ( I want to eventually include my app in another app where this might be implemented but isn't necessarily implemented using any particular security frameworks or limited to any)
I had an idea of creating some global variable user that could be referenced through out my application, or if I had to implement a system to do it all in this app that I could do so in in some abstract way so that different options could be injected in.
some of my ideas or understanding of what I should be doing may be completely wrong and ignorant of fundamentals but I genuinely do not know what approach I should take to do this.
In case it is relevant I currently don't have any back-end but eventually hope use MongoDB for storage and nodejs for services but I also want to try keep it open-ended to allow others to use different storage/backends such as sql and php
is there away to have a global uservariable/service that I could inject/populate from another (parent?) app?
If so what would be the best approach to do so?
If Not, why and what approach should I take and why?
Update
I Believe from comments online and some suggestion made to me that a service would be the best option BUT How would I go about injecting from a parent application into this applications service?
If your (single) page is rendered dynamically by the server and the server knows if you are logged-in or not, then you could do the following:
Dynamically render a script tag that produces:
<script>
window.user = { id: 1234, name: 'User A', isLoggedIn: true };
</script>
For non logged-in users:
<script>
window.user = { isLoggedIn: false };
</script>
For convinience, copy user to a value inside angular's IOC:
angular.module('myApp').value('user', window.user);
Then, you can use it in DI:
angular.module('myApp').factory('myService', function(user) {
return {
doSomething: function() {
if (user.isLoggedIn) {
...
} else {
...
}
}
};
});
Something tricky (which you should thing twice before doing [SEE COMMENTS]) is extending the $scope:
angular.module('myApp').config(function($provide) {
$provide.decorator('$controller', function($delegate, user) {
return function(constructor, locals) {
locals.$scope._user = user;
return $delegate(constructor, locals);
};
});
});
This piece of code decorates the $controller service (responsible for contructing controllers) and basically says that $scope objects prior to being passed to controllers, will be enhanced with the _user property.
Having it automatically $scoped means that you can directly use it any view, anywhere:
<div ng-if="_user.isLoggedIn">Content only for logged-in users</div>
This is something risky since you may end up running into naming conflicts with the original $scope API or properties that you add in your controllers.
It goes without saying that these stuff run solely in the client and they can be easily tampered. Your server-side code should always check the user and return the correct data subset or accept the right actions.
Yes you can do it in $rootScope. However, I believe it's better practice to put it inside a service. Services are singletons meaning they maintain the same state throughout the application and as such are prefect for storing things like a user object. Using a "user" service instead of $rootScope is just better organization in my opinion. Although technically you can achieve the same results, generally speaking you don't want to over-populate your $rootScope with functionality.
You can have a global user object inside the $rootScope and have it injected in all your controllers by simply putting it into the arguments of the controller, just as you do with $scope. Then you can implement functionalities in a simple check: if($rootScope.user). This allows you to model the user object in any way you want and where you want, acting as a global variable, inside of Angular's domain and good practices with DI.
Just to add on my comment and your edit. Here is what the code would look like if you wanted to be able to re-use your user service and insert it into other apps.
angular.module('user', []).service('userService', [function(){
//declare your user properties and methods
}])
angular.module('myApp', ['user'])
.controller('myCtrl', ['userService', '$scope', function(userService, scope){
// you can access userService from here
}])
Not sure if that's what you wanted but likewise you could have your "user" module have a dependency to another "parent" module and access that module's data the same way.

Resources