I want to set up an authentication system with tokens on my Go application, which use an AngularJS front-end.
What I'm looking for is advices about all steps to create a safe system. Here's my steps :
We will considerate a user entry is already written in our database.
1 - The user wants to sign in
The user goes to the index of the web app which prompts him to sign in.
With my app.yaml file, I declare my HTML file with dependencies for the AngularJS front-end:
application: authtest
version: 1
runtime: go
api_version: go1
handlers:
- url: /
static_files: frontend/index.html
upload: frontend/(.*\.html)
- url: /js
static_dir: frontend/js
- url: /.*
script: _go_app
Visual :
Code:
<form ng-submit="signIn()" ng-controller="signInCtrl">
<input type="email" ng-model="credentials.email" placeholder="Email" name="email">
<input type="password" ng-model="credentials.password" placeholder="Password" name="password">
<input type="submit" value="Sign in">
</form>
The user enters his credentials, and click on Sign in button.
2 - Request the server
The AngularJS module code:
<script>
angular.module('authtest', ['ngCookies'])
.controller('signInCtrl', ['$scope', '$http', '$window', '$cookieStore', '$route', function($scope, $http, $window, $cookieStore, $route){
var credentials = {}
$scope.signIn = function() {
$http.post('/signin', credentials)
.success(function (data, status) {
if(status == 200) {
if(data.Access_token){
//set cookies with tokens
$cookieStore.put('access_token', data.Access_token);
$cookieStore.put('refresh_token', data.Refresh_token);
$route.reload();
}
else {
$window.alert('Wrong credentials, try again.');
}
}
})
.error(function (data, status) {
$window.alert('error: ' + data + '(errorStatus: ' + status + ')');
});
};
}]);
</script>
The Angular module posts the form to /signin path, so the Go application needs to handle it:
package main
import (
"net/http"
"encoding/json"
"fmt"
)
type SignInCredentials struct {
Email string
Password string
}
type Token struct {
Access_token string
Refresh_token string
Id_token string
}
func init() { //I use init() instead of main() because I'm using App Engine.
http.HandleFunc("/signin", SignInHandler)
}
func SignInHandler (w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var c SignInCredentials
err := decoder.Decode(&c)
if err != nil {
panic()
}
var hashPassword = hash(c.Password) //Is it at a good level to hash it ?
if isInDatabase(c.Email, hashPassword) == false {
fmt.Fprintf(w, "") // Really useful ?
return
}
var tokens Token
/**
* The user seems to be well stored in the database, but how
* to manage my tokens ?
*/
response, _ := json.Marshal(tokens)
fmt.Fprintf(w, string(response))
}
Obviously, hashPassword(p string)
hashes the user password and isInDatabase(e string, p string)
is a boolean which checks if the provided credentials are stored in our database.
- As I said inside the code, I'm wondering if it's the good moment to hash the password of the user, or maybe hash it in client-side ?
- Print a zero-car string if the user is not in database is really useful or could I just return the function ?
- The main question here is how to manage my tokens ? I often see tokens are mainly composed of
access_token
,refresh_token
andid_token
. I also knowaccess_token
is limited in time to use (the current session, ot 3600seconds for example) and we userefresh_token
to have a fresh newaccess_token
. But how to generate it and store it ?
3 - Handle response with AngularJS
As already written in AngularJS module code, when the user is well authenticated, we set cookies with provided tokens. Is it a good way ? I'm also wondering how to prevent XSRF (CSRF) attacks in my system ?
Thank you for your future answers and advices.