diff --git a/bin/account-manager.pl.in b/bin/account-manager.pl.in
index 4356bf1a1a95d8edafe0c38e0b0ce33ed7a380f1..3a1bd57173e76eb171cfed49eee999654eb6cfc7 100755
--- a/bin/account-manager.pl.in
+++ b/bin/account-manager.pl.in
@@ -311,23 +311,26 @@ sub add_token {
         -verbose => 0
     ) unless $options{sp_entityid};
 
-    my $token = IdPAccountManager::AuthenticationToken->new(
+    # delete any previous token for the same email/service couple
+    my $old_token = IdPAccountManager::AuthenticationToken->new(
         db            => $db,
         email_address => $options{email_address},
         sp_entityid   => $options{sp_entityid}
     );
 
-    ## First remove token if on exist for this email+SP
-    if ($token->load(speculative => 1)) {
-        $token->delete() or die "failed to delete authentication token\n";
-
-        $token = IdPAccountManager::AuthenticationToken->new(
-            db            => $db,
-            email_address => $options{email_address},
-            sp_entityid   => $options{sp_entityid}
-        );
+    if ($old_token->load(speculative => 1)) {
+        $old_token->delete() or die "failed to delete authentication token\n";
     }
 
+    # compute a new token
+    my $token = IdPAccountManager::AuthenticationToken->new(
+        db            => $db,
+        email_address => $options{email_address},
+        sp_entityid   => $options{sp_entityid},
+        creation_date => DateTime->today(),
+        token         => IdPAccountManager::Tools::generate_token()
+    );
+
     $token->save() or die "failed to save authentication token\n";
 
     $token->print();
diff --git a/lib/IdPAccountManager/AuthenticationToken.pm b/lib/IdPAccountManager/AuthenticationToken.pm
index cbc33158c34751d6ebd950f8f34a05253b18264a..85292f608e31768542a8499929825203eca05e69 100644
--- a/lib/IdPAccountManager/AuthenticationToken.pm
+++ b/lib/IdPAccountManager/AuthenticationToken.pm
@@ -5,9 +5,6 @@ use warnings;
 
 use base 'IdPAccountManager::DB::Object';
 
-use Digest::MD5;
-use DateTime;
-
 __PACKAGE__->meta->setup(
     table   => 'authenticationtokens',
 
@@ -38,25 +35,4 @@ sub print {
       $self->creation_date()->strftime('%Y:%m:%d');
 }
 
-sub save {
-    my ($self) = @_;
-
-    # If no ID is defined, it is a new account
-    if (! defined $self->id()) {
-        $self->creation_date(DateTime->today());
-        $self->token(_generate_token($self->email_address()));
-    }
-
-    $self->SUPER::save();
-}
-
-sub _generate_token {
-    my ($salt, $size) = @_;
-    $size = 20 unless $size;
-
-    # ID is based on time + PID
-    return substr(Digest::MD5::md5_hex(time . $$ . $salt), -1 * $size);
-}
-
 1;
-
diff --git a/lib/IdPAccountManager/Tools.pm b/lib/IdPAccountManager/Tools.pm
index 9587f6ed0f21c7c2f4d7c74b9e98e3702936c3b0..bf3c930af79cbadc318c6ac6fa0ad678943edbbc 100644
--- a/lib/IdPAccountManager/Tools.pm
+++ b/lib/IdPAccountManager/Tools.pm
@@ -4,7 +4,9 @@ use strict;
 use warnings;
 
 use Digest::SHA;
+use Digest::MD5;
 use Encode;
+use English qw(-no_match_vars);
 use Template;
 
 # get SHA256 hash for a string
@@ -61,6 +63,14 @@ sub generate_password {
     return $rndstring;
 }
 
+# ID is based on time + PID
+sub generate_token {
+    my ($salt, $size) = @_;
+    $size = 20 unless $size;
+
+    return substr(Digest::MD5::md5_hex(time . $PID . $salt), -1 * $size);
+}
+
 ## Updates simpleSamlPhp authsources.php configuration file
 sub update_ssp_authsources {
     my ($templates_dir, $output, $accounts) = @_;
diff --git a/lib/IdPAccountManager/WebRequest.pm b/lib/IdPAccountManager/WebRequest.pm
index 7b40270ae99a3a27b64a73e513e2043c119bf100..d6c384cb89989cf8fcfee67e9a06bbcb74162e30 100644
--- a/lib/IdPAccountManager/WebRequest.pm
+++ b/lib/IdPAccountManager/WebRequest.pm
@@ -319,30 +319,33 @@ sub req_generate_token {
         return;
     }
 
-    my $token = IdPAccountManager::AuthenticationToken->new(
+    # delete any previous token for the same email/service couple
+    my $old_token = IdPAccountManager::AuthenticationToken->new(
         db            => $self->{db},
         email_address => $self->{in}->{email_address},
         sp_entityid   => $self->{in}->{sp_entityid}
     );
 
-    ## First remove token if one exist for this email+SP
-    if ($token->load(speculative => 1)) {
-        unless ($token->delete()) {
+    if ($old_token->load(speculative => 1)) {
+        unless ($old_token->delete()) {
             push @{ $self->{out}->{errors} }, "internal";
             $self->{logger}->errorf(
                 "Failed to delete previous authentication token with ID %s",
-                $token->id()
+                $old_token->id()
             );
             return;
         }
-
-        $token = IdPAccountManager::AuthenticationToken->new(
-            db            => $self->{db},
-            email_address => $self->{in}->{email_address},
-            sp_entityid   => $self->{in}->{sp_entityid}
-        );
     }
 
+    # compute a new token
+    my $token = IdPAccountManager::AuthenticationToken->new(
+        db            => $self->{db},
+        email_address => $self->{in}->{email_address},
+        sp_entityid   => $self->{in}->{sp_entityid},
+        creation_date => DateTime->today(),
+        token         => IdPAccountManager::Tools::generate_token()
+    );
+
     unless ($token->save()) {
         push @{ $self->{out}->{errors} }, "internal";
         $self->{logger}->error("Failed to save authentication token");