How To: Create a login form for your application

There are a few important considerations when deciding how to implement the login form for your application. You need to consider, foremost, the security of your user's credentials. You need to provide a mechanism for sessions to expire automatically, so a user who forgets to log out doesn't leave his access available to someone who later uses the same computer. All of these considerations provided the motivation behind time-limited authentication tokens in the API. These provide a limited-time access code that can be used in place of a normal password to provide access to the API. Once they expire, they are gone forever. So, on to the implementation. The process basically boils down to these steps:

  1. Authenticate the User
  2. Store the Credentials
  3. Use the Credentials for API Requests
  4. Deal With Credential Expiration

Authenticate the User

You'll need first to provide a form that requires the user to enter their real username and password to authenticate against the API. All examples in this tutorial are written as if you're writing a web-based application using HTML, with the server-side language examples in Perl.

Your form would look something like this:

<form action="login.pl" method="POST">
	<label for="username">Username</label>
	<input type="text" name="username" id="username">

	<label for="password">Password</label>
	<input type="password" name="password" id="password">

	<input type="submit" value="Login">
</form>

Pretty straightforward login form. Once the user submits that form, you can validate their credentials by attempting to get an API auth token using those credentials. In Perl, it would look something like:

#!/usr/local/bin/lwperl
use strict;
use LWP::UserAgent;
use HTTP::Request;
use JSON;

my $ua = LWP::UserAgent->new;
$ua->timeout(30);

# fake method 'get_input' grabs the POST'ed parameters, this would be replaced
# by however your app has it set up to grab parameters

my $username = &get_input('username');
my $password = &get_input('password');

my $req = HTTP::Request->new(POST => "https://api.stormondemand.com/v1/account/auth/token");
$req->authorization_basic($username, $password);

my $response = $ua->request($req);
my $code = $response->code;

if ($code == 401 || $code == 403) {
	# the credentials are invalid, show the user an error
}
elsif ($code == 200) {
	my $results = JSON::decode_json($response->content);

	if ($results->{error_class}) {
		# the api returned an error condition, deal with it
	}
	else {
		# successful login, do what you need
	}
}
else {
	# some other error occurred, deal with it
}

Store the Credentials

Once you validate the credentials and get a valid token in the above code, you should store that token in your session. Do not store the user's real password in the session, and never store either piece of data in a cookie on the user's computer.

# fake method 'get_my_session' should be replaced with however you are dealing with sessions
my $session = &get_my_session();
$session->{username} = $results->{username};
$session->{token}    = $results->{token};

Now we have valid, temporary credentials to use for any actual api calls we wish to make in our application.

Use the Credentials for API Requests

Now that we have some stored credentials, we can actually get to doing something useful in our application. Let's start off by getting a list of all of the servers in my account.

#!/usr/local/bin/lwperl
use strict;
use LWP::UserAgent;
use HTTP::Request;
use JSON;

my $ua = LWP::UserAgent->new;
$ua->timeout(30);

my $session = &get_my_session();

my $req = HTTP::Request->new(POST => "https://api.stormondemand.com/v1/storm/server/list");
$req->authorization_basic($session->{username}, $session->{token});

my $response = $ua->request($req);
my $code = $response->code;

if ($code == 200) {
	my $results = JSON::decode_json($response->content);

	if ($results->{error_class}) {
		# the api returned an error condition, deal with it
	}
	else {
		# now you have a server list, do something with it
		foreach my $server (@{ $results->{items} }) {
			# display something?
		}
	}
}
else {
	# some error occurred, deal with it
}

Deal With Credential Expiration

The auth token can continue to be used until it expires, at which point, we'll need to prompt the user to login again. When you receive an HTTP response code of 403, that is an indication that the credentials are not valid any longer.

#!/usr/local/bin/lwperl
use strict;
use LWP::UserAgent;
use HTTP::Request;
use JSON;

my $ua = LWP::UserAgent->new;
$ua->timeout(30);

my $session = &get_my_session();

my $req = HTTP::Request->new(POST => "https://api.stormondemand.com/v1/storm/server/list");
$req->authorization_basic($session->{username}, $session->{token});

my $response = $ua->request($req);
my $code = $response->code;

if ($code == 403) {
	# credentials have expired, show them the login form again

}

Obviously you would want to wrap all of this error handling logic into a generic client library, which is what we'll be covering in the next tutorial.