diff --git a/bin/account-manager-client.pl b/bin/account-manager-client.pl
index 2e564b6e188f6f8493f26738c54b0aafa4be40b6..ae6ad372e2f03e753c3bdfb6d41e263636af659d 100755
--- a/bin/account-manager-client.pl
+++ b/bin/account-manager-client.pl
@@ -8,11 +8,12 @@ use utf8;
 use lib "/opt/testidp/IdPAccountManager/lib";
 
 use Getopt::Long;
+use POSIX;
 
 use IdPAccountManager::TestAccount;
 
 my %options;
-unless (&GetOptions(\%options, 'help', 'create_test_account', 'account_profile=s', 'sp_entityid=s')) {
+unless (&GetOptions(\%options, 'help', 'create_test_account', 'account_profile=s', 'sp_entityid=s', 'list_test_accounts')) {
     die "Unknown options.";
 }
 
@@ -35,4 +36,23 @@ if ($options{'create_test_account'}) {
     unless (defined $test_account) {
         die "Failed to create test account";
     }
+}elsif ($options{'list_test_accounts'}) {
+    
+    my %args;
+    if ($options{'sp_entityid'}) {
+        push @{$args{'query'}}, 'sp_entityid' => $options{'sp_entityid'};
+    }
+    
+    if ($options{'account_profile'}) {
+        push @{$args{'query'}}, 'account_profile' => $options{'account_profile'};
+    }
+    
+    
+    my $all = IdPAccountManager::TestAccount::list_test_accounts(%args);
+    
+    foreach my $test_account (@$all) {
+        printf "Account ID=%s; password=%s; sp_entityid=%s; account_profile=%s; creation_date=%s; expiration_date=%s\n",
+            $test_account->id, $test_account->user_password, $test_account->sp_entityid, $test_account->account_profile,
+            &POSIX::strftime('%Y:%m:%d', localtime($test_account->creation_date)), &POSIX::strftime('%Y:%m:%d', localtime($test_account->expiration_date));
+    }
 }
diff --git a/bin/expire-test-accounts.pl b/bin/expire-test-accounts.pl
new file mode 100755
index 0000000000000000000000000000000000000000..24ed1b7ffc2db35807122d04ed8393f240a981c5
--- /dev/null
+++ b/bin/expire-test-accounts.pl
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+
+## 09/09/2014, Olivier Salaün
+## Command-line script to remove expired test accounts
+## The script also updates the simpleSamlPhp config file
+
+use strict;
+use utf8;
+use lib "/opt/testidp/IdPAccountManager/lib";
+
+use Getopt::Long;
+use POSIX;
+
+use IdPAccountManager::TestAccount;
+
+my %options;
+unless (&GetOptions(\%options, 'help', 'list_only')) {
+    die "Unknown options.";
+}
+
+if ($options{'help'}) {
+    printf "$0 --list_only\n";
+}
+            
+if ($options {'list_only'}) {
+    my $all = IdPAccountManager::TestAccount::list_test_accounts('query' => ['expiration_date' => {lt => time}]);
+    
+    foreach my $test_account (@$all) {
+        printf "Account ID=%s; password=%s; sp_entityid=%s; account_profile=%s; creation_date=%s; expiration_date=%s\n",
+            $test_account->id, $test_account->user_password, $test_account->sp_entityid, $test_account->account_profile,
+            &POSIX::strftime('%Y:%m:%d', localtime($test_account->creation_date)), &POSIX::strftime('%Y:%m:%d', localtime($test_account->expiration_date));
+    }
+    
+}else {
+    ## Remove expired test accounts
+    my $all = IdPAccountManager::TestAccount::list_test_accounts('query' => ['expiration_date' => {lt => time}]);
+    
+    printf "Removing expired test accounts...\n";
+    foreach my $test_account (@$all) {
+        printf "\tAccount ID=%s; password=%s; sp_entityid=%s; account_profile=%s; creation_date=%s; expiration_date=%s\n",
+            $test_account->id, $test_account->user_password, $test_account->sp_entityid, $test_account->account_profile,
+            &POSIX::strftime('%Y:%m:%d', localtime($test_account->creation_date)), &POSIX::strftime('%Y:%m:%d', localtime($test_account->expiration_date));
+        $test_account->delete || die;
+    }
+    printf "%d accounts removed\n", $#{$all}+1;
+
+    #&IdPAccountManager::Tools::dump_var(\%IdPAccountManager::Conf::global, 0, \*STDOUT);
+
+    ## Update simpleSamlPhp configuration file
+    printf "Update simpleSamlPhp configuration file...\n";
+
+    IdPAccountManager::Tools::update_ssp_authsources();
+}
+
+
diff --git a/conf/create-manager-db.sql b/conf/create-manager-db.sql
index 1e51272bd4e3c6b42cae600f5028d5beceade95b..e55833b93e0d4845944f270d360c7e5e89f68ea0 100644
--- a/conf/create-manager-db.sql
+++ b/conf/create-manager-db.sql
@@ -2,11 +2,11 @@
 
 CREATE TABLE `testaccounts` (
   `id` bigint(20) NOT NULL auto_increment,
-  `user_id` varchar(50) NOT NULL,
   `user_password` varchar(50) NOT NULL,
   `creation_date` int default NULL,
   `expiration_date` int default NULL,
-  PRIMARY KEY  (`id`),
-  UNIQUE (user_id)
+  `account_profile` varchar(100) NOT NULL,
+  `sp_entityid` varchar(250) NOT NULL,
+  PRIMARY KEY  (`id`)
 ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ;
 
diff --git a/lib/IdPAccountManager/Data/Testaccount.pm b/lib/IdPAccountManager/Data/Testaccount.pm
index fa1613ab801cd15cc5152a6ecfd0a19c66adcfe1..b5b82387aaf7ddbd49a10101c7659ea8a99dffc8 100644
--- a/lib/IdPAccountManager/Data/Testaccount.pm
+++ b/lib/IdPAccountManager/Data/Testaccount.pm
@@ -8,12 +8,12 @@ __PACKAGE__->meta->setup(
     table   => 'testaccounts',
 
     columns => [
-        id                     => { type => 'bigserial', not_null => 1 },
-        user_password          => { type => 'varchar', length => 50, not_null => 1 },
-        creation_date          => { type => 'integer' },
-        expiration_date        => { type => 'integer' },
-        account_profile        => { type => 'varchar', length => 100, not_null => 1 },
-        relying_party_entityid => { type => 'varchar', length => 250, not_null => 1 },
+        id              => { type => 'bigserial', not_null => 1 },
+        user_password   => { type => 'varchar', length => 50, not_null => 1 },
+        creation_date   => { type => 'integer' },
+        expiration_date => { type => 'integer' },
+        account_profile => { type => 'varchar', length => 100, not_null => 1 },
+        sp_entityid     => { type => 'varchar', length => 250, not_null => 1 },
     ],
 
     primary_key_columns => [ 'id' ],
diff --git a/lib/IdPAccountManager/TestAccount.pm b/lib/IdPAccountManager/TestAccount.pm
index de034a59597730cafbcb203b666fdf57dee72c78..aee85a929a6a45c91df3806a9e6ea66a73e9c0d3 100644
--- a/lib/IdPAccountManager/TestAccount.pm
+++ b/lib/IdPAccountManager/TestAccount.pm
@@ -1,5 +1,11 @@
 package IdPAccountManager::TestAccount;
 
+use IdPAccountManager::Data::Testaccount;
+use IdPAccountManager::Data::Testaccount::Manager;
+
+use IdPAccountManager::Tools;
+use IdPAccountManager::Conf;
+
 use Moose;
 use Moose::Util::TypeConstraints;
 
@@ -8,7 +14,7 @@ subtype 'entityid',
     where { /^(urn:|http(s)?\:\/\/)/ },
     message { "$_ is not a valide entityid"};
 
-has 'account_profile' => (is => 'ro',
+has 'account_profile' => (is => 'rw',
                           isa => 'Str',
                           required => 1);
 has 'sp_entityid' => (is => 'rw',
@@ -16,6 +22,31 @@ has 'sp_entityid' => (is => 'rw',
                       required => 1,
                       );
 
+sub BUILD {
+    
+    my $self = shift;
+    my $args = shift;
+    
+    my $testaccount_db = IdPAccountManager::Data::Testaccount->new('account_profile' => $args->{'account_profile'},
+                                                                   'sp_entityid' => $args->{'sp_entityid'},
+                                                                   'user_password' => &IdPAccountManager::Tools::generate_password(),
+                                                                   'creation_date' => time,
+                                                                   'expiration_date' => time + ($IdPAccountManager::Conf::global{'accounts_validity_period'} * 3600 * 24));
+    $testaccount_db->save();
+    
+    ## TODO : update IdP conf file; given the account profile
+}
+
+## list all test accounts
+## Class method
+sub list_test_accounts {
+    my %args = @_;
+
+    my $all = IdPAccountManager::Data::Testaccount::Manager->get_testaccounts(%args);
+    
+    return $all;
+}
+
 #before 'new' => sub { print "about to call new\n"; };
 
 1; # Magic true value required at end of module
diff --git a/templates/accountProfiles/student1.tt2 b/templates/accountProfiles/student1.tt2
new file mode 100644
index 0000000000000000000000000000000000000000..64095dd17eef0321161a7a11a327b6c6804082dc
--- /dev/null
+++ b/templates/accountProfiles/student1.tt2
@@ -0,0 +1,13 @@
+'user[% account.id %]:[% account.user_password %]' => array(
+	'uid' => 'user[% account.id %]',
+	'eduPersonAffiliation' => array('member', 'student'),
+	'eduPersonScopedAffiliation' => array('member@[% conf.idp_scope %]', 'student@[% conf.idp_scope %]'),
+        'displayName' => 'John Kleinman',
+        'cn' => 'John Kleinman',
+        'mail' => 'john.kleinman@[% conf.idp_scope %]',
+        'eduPersonPrincipalName' =>'[% account.id %]@[% conf.idp_scope %]',
+        'eduPersonTargetedID' =>'[% conf.idp_entityid %]![% account.sp_entityid %]!X622UR2A7PG1uVhATobBOrMz+Ys=',
+        'schacHomeOrganization' => '[% conf.idp_scope %]',
+        'schacHomeOrganizationType' => 'urn:schac:homeOrganizationType:int:university',
+	'associatedSP' => '[% account.sp_entityid %]',
+),
diff --git a/templates/accountProfiles/valid-accounts.php.tt2 b/templates/accountProfiles/valid-accounts.php.tt2
new file mode 100644
index 0000000000000000000000000000000000000000..7195810f53ce6f51e83cc9a3ff9690081b1449e3
--- /dev/null
+++ b/templates/accountProfiles/valid-accounts.php.tt2
@@ -0,0 +1,8 @@
+// template for a PhP configuration file loaded in simpleSamlPhp authsources.php file
+$validTestAccounts = array (
+    'exampleauth:UserPass',
+
+[% FOREACH account IN accounts %]
+  [% INCLUDE "${account.account_profile}.tt2" %]
+[% END %]
+);