In the design there is a login screen with three options: facebook, twitter or email login. The purpose of each is just to get some kind of identifier to keep the users separated. Also I try to prevent misuse of other's account. In Finland there is a law for identity registry. I try to avoid making a one. Well, to be honest it's not really a problem since there needs to be one author for registry and the purpose of the registry needs to available.
Facebook login
Facebook was the easiest to work with. You copy-paste a code snippet from facebook's dev page and call for login. A separate window opens and you authorise the application to see your public profile. There is a callback, which I used localhost:8001/ , and it worked out of the box. With the confidentiality from the small task I got forward with twitter login.
Twitter login
Twitter login was its own beast. It was based on OAuth, well someone said Facebook is also using that but you didn't need to worry about internals. In every place there was a warning note that you should not implement client side authorisation. That's what I was to do in any case. Like it or not. The problem being that I needed to expose the application keys to all in public (javascript file). To fix this I set the application to read only mode. It can read the public profile of twitter, exactly what I need.
The biggest problem with twitter was javascript libraries. There was only few and many of them was designed to work with nodejs. Although, I like javascript I am not yet found love with nodejs. Finally I found Codebird library. The implementation looked nice (read, it had a nice tutorial with examples) and it seemed to do what I was looking for. The problem with twitter application settings was that it was not able to work with localhost. I edited my /etc/hosts to include alias for localhost called www.localhost.com. This worked like a charm but it took quite a lot of time to understand what key was used where. Twitter developer documentation was not really helping. When I finally got it to work it all seemed easy but before that it was horrible way of errors.
function CB() {
var cb = new Codebird;
cb.setConsumerKey("KEY", "SECRET");
return cb;
}
// This will be called when button is clicked.
function twLogin() {
var cb = CB();
// gets a request token
cb.__call(
"oauth_requestToken",
// This was the most confusing parameter since OAuth allows Out-of-band authentication too.
// In this case user would have to insert a PIN code found from verify page. UX--
{}, //{oauth_callback: "oob"},
function (reply) {
// stores it
cb.setToken(reply.oauth_token, reply.oauth_token_secret);
localStorage.setItem('token', reply.oauth_token);
localStorage.setItem('token_secret', reply.oauth_token_secret);
// gets the authorize screen URL
cb.__call(
"oauth_authorize",
{},
function (auth_url) {
window.open(auth_url);
}
);
}
);
}
// The callback function calls this page again with query parameter "oauth_verifier".
// With verifier we can finish the authorization.
(function(){
var query = location.search.substr(1).split("&");
var parameters = {};
var parameter;
for (var i = 0; i < query.length; i++) {
parameter = query[i].split("=");
if (parameter.length === 1) {
parameter[1] = "";
}
parameters[decodeURIComponent(parameter[0])] = decodeURIComponent(parameter[1]);
}
// check if oauth_verifier is set by callback function
if (typeof parameters.oauth_verifier !== "undefined" && localStorage.getItem('token')) {
var cb = CB();
cb.setToken(localStorage.getItem('token'), localStorage.getItem('token_secret'));
cb.__call(
"oauth_accessToken",
{
oauth_verifier: parameters.oauth_verifier
},
function (reply) {
if (reply.httpstatus == 200) {
// reply.screen_name is twitter username
}
}
);
}
})();
Domain name
I started to think if there would be free domain names. Luckily internet offers everything. freenom.com has free domain names for .tk, .ml, .ga and .cf. I guess there are also other name providers but I registered stoningrosetta.cf from freenom. Keep costs low you know. And name just feels really good. I can fully understand why it is very important to remember people names, it feels good when someone recognises you. And now my project can be recognised, yeah.
Email login
2/3 was implemented. Now things got more harder, how to do email login? My idea was following: user sends email to server which would send a special login link to user's email (hash of email + salt). I started to look AWS services how to implement the email sending. Simple Email Service provides API to send messages. The API, however, was not the easiest to understand at all. There was some kind of signature routine but luckily there was a project implementing a library for AWS in erlang already, https://github.com/lookio/eaws. There was small issue, however. Host of the API service was hard coded so I created a fork and fixed the host to be dynamic. That's it.
The erlang code looks something like this. I still don't know if the connect is needed but without it nothing is sent. So there is some kind of erlang internal server or something. I don't yet fully understand erlang concepts.
eaws_client:connect(),
eaws_client:send_formatted_email([
{to_addresses, [binary_to_list(Email)]},
{from_address, "noreply@stoningrosetta.cf"},
{subject, "Stoning Rosetta"},
{text_body, "Here is a login link for your game: " ++ binary_to_list(Uniq) },
{html_body, ""}
]),
As you can see the from address is noreply at stoninrosetta.cf. So how this should work? SES (Simple Email Service) can only send emails from verified users or domains. How to verify the domain for AWS? SES has it's own way to work. First you need to make AWS as your email server with MX record in your domain config. Then you need to add verification code with TXT record. The final configuration can be seen in below. The freenom had issue with normal AWS verification process since the record name cannot have underscore for the needed _amazonses. The other method used amazonses: prefix in value which worked fine.
In couple of hours I got following email from AWS:
Amazon Web Services
Congratulations! The Amazon SES verification process for the domain stoningrosetta.cf in
region EU (Ireland) is now complete. You are now able to send email through Amazon SES
from any address within this domain. For more information, please refer to the Amazon SES Developer Guide.
Thank you for using Amazon SES.
And after that I received my first test emails flawlessly.