diff --git a/bin/account-manager-client.pl b/bin/account-manager-client.pl
index 8f98bfaa0c6227da24c9d64c3ca2a15ae5012b2f..9e2ecc48e18789fb674f67e89b2a45b643dae237 100755
--- a/bin/account-manager-client.pl
+++ b/bin/account-manager-client.pl
@@ -17,7 +17,7 @@ use IdPAccountManager::ServiceProvider;
 use IdPAccountManager::AuthenticationToken;
 
 my %options;
-unless (&GetOptions(\%options, 'help', 'add_test_account', 'account_profile=s', 'sp_entityid=s', 'list_test_accounts', 'parse_federation_metadata', 'list_service_providers','list_authentication_tokens', 'add_authentication_token','email_address=s')) {
+unless (&GetOptions(\%options, 'help', 'add_test_account', 'account_profile=s', 'sp_entityid=s', 'list_test_accounts', 'parse_federation_metadata', 'list_service_providers','list_authentication_tokens', 'get_authentication_token', 'add_authentication_token','email_address=s','token=s')) {
     die "Unknown options.";
 }
 
@@ -108,17 +108,45 @@ if ($options{'add_test_account'}) {
 }elsif ($options{'list_authentication_tokens'}) {
     
     my %args;    
+    if ($options{'sp_entityid'}) {
+        push @{$args{'query'}}, 'sp_entityid' => $options{'sp_entityid'};
+    }
+    if ($options{'token'}) {
+        push @{$args{'query'}}, 'token' => $options{'token'};
+    }
     
     my $all = IdPAccountManager::AuthenticationToken::list_authentication_tokens(%args);
     
     if ($#{$all} < 0) {
-        printf "No token in DB\n";
+        printf "No corresponding token found in DB\n";
     }
     
     foreach my $authentication_token (@$all) {
         $authentication_token->print();
     }
     
+}elsif ($options{'get_authentication_token'}) {
+    
+    my %args;    
+    if ($options{'token'}) {
+        $args{'token'} = $options{'token'};
+    }
+    
+    my $authentication_token = new IdPAccountManager::AuthenticationToken(%args);
+    
+    unless ($authentication_token->load()) {
+        die "No corresponding token found in DB\n";
+    }
+    
+    if ($options{'sp_entityid'}) {
+        unless ($authentication_token->get('sp_entityid') eq $options{'sp_entityid'}) {
+            die "Authentication token cannot be used for this SP\n";
+        }
+    }
+
+    
+    $authentication_token->print();
+
 }elsif ($options{'add_authentication_token'}) {
     
     unless ($options{'email_address'}) {
diff --git a/bin/account-manager-web.pl b/bin/account-manager-web.pl
index eaf7e61cf25f0f134e2ccb5c88d0bde0b50cbc26..d7c1f5151ff98f0069f870b4d128eecdb19cae71 100755
--- a/bin/account-manager-web.pl
+++ b/bin/account-manager-web.pl
@@ -35,6 +35,7 @@ my %format = (
 my %actions = ('select_sp' => {'title_en' => 'Select your Service Provider'    },
                'get_sp_list' => {'title_en' => 'Select your Service Provider'    },
                'generate_token' => {'title_en' => 'Generate an authentication token'},
+               'validate_token' => {'title_en' => 'Validate an authentication token'},
     );
 
 ## Gives writes for the group
@@ -332,4 +333,68 @@ sub req_generate_token {
     return 1;
 }
 
+## Validate an authentication token 
+## Test accounts get created
+## Sample call : dev-edugain.renater.fr/accountmanager?action=validate_token&style=nobanner&sp_entityid=https%3A%2F%2Fsourcesup.cru.fr%2Fshibboleth&authentication_token=c1cfecb51ea40d39a695
+sub req_validate_token {
+    my $self = shift;
+    &IdPAccountManager::Tools::do_log('info', "");
+    
+    unless ($self->{'param_in'}{'sp_entityid'}) {
+        push @{$self->{'param_out'}{'errors'}}, "missing_sp_entityid";
+	&IdPAccountManager::Tools::do_log('error', "Missing parameter sp_entityid");
+	return undef;
+    }
+
+    unless ($self->{'param_in'}{'authentication_token'}) {
+        push @{$self->{'param_out'}{'errors'}}, "missing_authentication_token";
+	&IdPAccountManager::Tools::do_log('error', "Missing parameter authentication_token");
+	return undef;
+    }
+
+    my $authentication_token = new IdPAccountManager::AuthenticationToken(token => $self->{'param_in'}{'authentication_token'});
+    
+    unless ($authentication_token->load()) {
+ 	push @{$self->{'param_out'}{'errors'}}, "wrong_token";
+	&IdPAccountManager::Tools::do_log('error', "Failed to validate authentication token %s for sp_entityid %s",
+                                          $self->{'param_in'}{'token'}, $self->{'param_in'}{'sp_entityid'});
+	return undef;
+    }
+    
+    unless ($authentication_token->get('sp_entityid') eq $self->{'param_in'}{'sp_entityid'}) {
+  	push @{$self->{'param_out'}{'errors'}}, "wrong_token_for_sp";
+	&IdPAccountManager::Tools::do_log('error', "Authentication token %s cannot be used for SP with entityid %s",
+                                          $self->{'param_in'}{'token'}, $self->{'param_in'}{'sp_entityid'});
+	return undef;
+    }
+   
+    ## delete the token
+    unless ($authentication_token->delete()) {
+        &IdPAccountManager::Tools::do_log('error', "Failed to delete authentication token %s",
+                                          $self->{'param_in'}{'token'});
+    }
+    
+    ## create test accounts
+    my @test_accounts = &IdPAccountManager::TestAccount::create_test_accounts_for_sp(sp_entityid => $self->{'param_in'}{'sp_entityid'});
+    
+    unless (@test_accounts) {
+  	push @{$self->{'param_out'}{'errors'}}, "accounts_creation_failed";
+	&IdPAccountManager::Tools::do_log('error', "Failed to create test accounts for SP with entityid %s",
+                                          $self->{'param_in'}{'sp_entityid'});
+	return undef;        
+    }
+    
+    ## Update simpleSAMLphp configuration to enable test accounts
+    unless (&IdPAccountManager::Tools::update_ssp_authsources()) {
+  	push @{$self->{'param_out'}{'errors'}}, "accounts_creation_failed";
+	&IdPAccountManager::Tools::do_log('error', "Failed to create simpleSAMLphp configuration file");
+	return undef;        
+    }
+    
+    $self->{'param_out'}{'sp_entityid'} = $self->{'param_in'}{'sp_entityid'};
+    $self->{'param_out'}{'test_accounts'} = \@test_accounts;
+    
+    return 1;
+}
+
 
diff --git a/lib/IdPAccountManager/AuthenticationToken.pm b/lib/IdPAccountManager/AuthenticationToken.pm
index 94ede6f36c78cd9fc34540e38ce4184e91553c02..4399f380a6b2ead2d80f9e6f0694310e278e96da 100644
--- a/lib/IdPAccountManager/AuthenticationToken.pm
+++ b/lib/IdPAccountManager/AuthenticationToken.pm
@@ -41,6 +41,13 @@ sub new {
     return $self;
 }
 
+## Load an authentication token from DB
+sub load {
+    my $self = shift;
+    
+    return $self->{'persistent'}->load(speculative => 1);
+}
+
 ## Get object parameter
 sub get {
     my $self = shift;
diff --git a/lib/IdPAccountManager/TestAccount.pm b/lib/IdPAccountManager/TestAccount.pm
index 22cf234324979d3ad66b62b512a57b6f3eb6c493..b052b837f113ac4f64986a7b38999e726933cdbb 100644
--- a/lib/IdPAccountManager/TestAccount.pm
+++ b/lib/IdPAccountManager/TestAccount.pm
@@ -106,6 +106,35 @@ sub list_test_accounts {
     return $accounts;
 }
 
+## create test accounts for all active account profiles
+sub create_test_accounts_for_sp {
+    my %args = @_;
+    my @test_accounts;
+    
+    unless ($args{'sp_entityid'}) {
+        IdPAccountManager::Tools::do_log('error',"Failed to create test account");
+        return undef;
+    }
+    
+    foreach my $profile (@{$Conf::global{'account_profiles'}}) {
+        my $test_account = new IdPAccountManager::TestAccount(account_profile => $profile,
+                                                              sp_entityid => $args{'sp_entityid'});
+        unless (defined $test_account) {
+             IdPAccountManager::Tools::do_log('error',"Failed to create test account");
+             return undef;
+        }
+        
+        unless ($test_account->save()) {
+            IdPAccountManager::Tools::do_log('error',"Failed to create test account");
+            return undef;
+        }
+        
+        push @test_accounts, $test_account;
+    }
+
+    return @test_accounts;
+}
+
 #before 'new' => sub { print "about to call new\n"; };
 
 1; # Magic true value required at end of module
diff --git a/templates/accountProfiles/teacher1.tt2 b/templates/accountProfiles/teacher1.tt2
new file mode 100644
index 0000000000000000000000000000000000000000..a40a063ef54cf15aadc36caaeba994fe0a7c7966
--- /dev/null
+++ b/templates/accountProfiles/teacher1.tt2
@@ -0,0 +1,13 @@
+'user[% account.get('id') %]:{SHA256}[% account.get('user_password_hash') %]=' => array(
+	'uid' => 'user[% account.get('id') %]',
+	'eduPersonAffiliation' => array('member', 'faculty'),
+	'eduPersonScopedAffiliation' => array('member@[% conf.idp_scope %]', 'faculty@[% conf.idp_scope %]'),
+        'displayName' => 'Peter Smith',
+        'cn' => 'Peter Smith',
+        'mail' => 'peter.smith@[% conf.idp_scope %]',
+        'eduPersonPrincipalName' =>'[% account.get('id') %]@[% conf.idp_scope %]',
+        'eduPersonTargetedID' =>'[% conf.idp_entityid %]![% account.get('sp_entityid') %]!X622UR2A7PG1uVhATobBOrMz+Ys=',
+        'schacHomeOrganization' => '[% conf.idp_scope %]',
+        'schacHomeOrganizationType' => 'urn:schac:homeOrganizationType:int:university',
+	'associatedSP' => '[% account.get('sp_entityid') %]',
+),
diff --git a/templates/mail/send_authentication_token.tt2.eml b/templates/mail/send_authentication_token.tt2.eml
index cfc11cd508ea1379a1633f4984e0e12970e76930..aea1425f8e82b9bce6895417b1ecdc205fc2b8a3 100644
--- a/templates/mail/send_authentication_token.tt2.eml
+++ b/templates/mail/send_authentication_token.tt2.eml
@@ -4,10 +4,10 @@ Subject: [% conf.app_name %] - Test accounts request
 Content-type: text/plain; charset=UTF-8; format=flowed
 
 This is an email challenge automatically sent to you by [% conf.app_name %]. Somebody has requested creation of test accounts
-for the service provider with entityid [% sp_entityid %] declared in eduGAIN interfederation. You are listed as
-contact for this service provider in eduGAIN metadata.
+for the service provider with entityid [% sp_entityid %]. This SAML entity is registered with eduGAIN interfederation.  You are
+identified as a contact for this service provider within eduGAIN metadata.
 
-To complete test accounts activation you should copy and paste the validation token below in the [% conf.app_name %] web form.
+To complete these test accounts creation, paste the following validation token on the [% conf.app_name %] web form.
 Validation token:  [% authentication_token %]
 
-
+[% conf.app_name %]: [% conf.app_url %]
\ No newline at end of file
diff --git a/templates/web/content.tt2.html b/templates/web/content.tt2.html
index 5036c762897fbd0876eb9944764485266a9643c8..3e9714208657b32603be52996c1fe332c2283b0d 100644
--- a/templates/web/content.tt2.html
+++ b/templates/web/content.tt2.html
@@ -28,6 +28,13 @@
   An error occured
  [% END %]
 
+[% ELSIF action == 'validate_token' %]
+ [% TRY %]
+  [% PROCESS 'templates/web/validate_token.tt2.html' %]
+ [% CATCH %]
+  An error occured
+ [% END %]
+
 [% ELSE %]
 Error: unknown action
 
diff --git a/templates/web/errors.tt2.html b/templates/web/errors.tt2.html
index 5cfe4b42095c55e5f44ad41ac15db046bde72fac..40261757769bde1fe91ea38e3785df1b0fb68124 100644
--- a/templates/web/errors.tt2.html
+++ b/templates/web/errors.tt2.html
@@ -1,3 +1,4 @@
+[% IF errors %]
  [% FOREACH err IN errors %]
 
 <p class="ui-state-error ui-corner-all" style="margin-top: 20px; padding: 0 .7em;"><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>
@@ -9,6 +10,15 @@
   [% ELSIF err == 'internal' %]
    internal error; administrators of the federation registry have been notified.
 
+  [% ELSIF err == 'wrong_token' %]
+   the validation token you provided is incorrect or it has already been used
+
+  [% ELSIF err == 'wrong_token_for_sp' %]
+   the validation token you provided cannot be used to obtain test accounts for this service provider ([% sp_entityid %])
+
+  [% ELSIF err == 'accounts_creation_failed' %]
+   failed to create your test accounts
+   
   [% ELSIF (matches = err.match('missing_(\w+)')) %]
    missing parameter '[% matches.0 %]'
 
@@ -19,3 +29,6 @@
 </p>
 <br/>
  [% END %] <!-- FOREACH -->
+ 
+ You can report the issue to the administrators (<a href="mailto:[% conf.support_email %]>[% conf.support_email %]</a>).
+[% END %]
diff --git a/templates/web/generate_token.tt2.html b/templates/web/generate_token.tt2.html
index f2d8ae944ccd3e0b155d973ef4d2510fbe2fe905..83581d919625da3e14595d141abb87216c99c59f 100644
--- a/templates/web/generate_token.tt2.html
+++ b/templates/web/generate_token.tt2.html
@@ -5,7 +5,7 @@ An email challenge including a validation token has been emailed to you at [% em
 
 <fieldset>
     <legend>Provide token</legend>
-   <label for="authentication_token">PLease provide the secret token here :</label>
+   <label for="authentication_token">Please provide the secret token here :</label>
 
 <input name="authentication_token" value="" id="authentication_token" type="text" class="required"/>
 
diff --git a/templates/web/get_sp_list.tt2.html b/templates/web/get_sp_list.tt2.html
index 1821ba8d2334fa467e59c06febbf299c6ca154a5..34f43683d9b0d5843c70404d3c9c878f015dab14 100644
--- a/templates/web/get_sp_list.tt2.html
+++ b/templates/web/get_sp_list.tt2.html
@@ -26,7 +26,7 @@ jQuery(document).ready(function($){
                 });
             }
 
-            // Trigger loading of the 'select_sp' with the selected SP entityid as parameter
+            // Trigger loading of the 'generate_token' with the selected SP entityid as parameter
             // Result gets included in the next tab
             if (currentIndex === 1 && newIndex === 2)
             {
@@ -39,6 +39,19 @@ jQuery(document).ready(function($){
                 });
             }
 
+            // Trigger loading of the 'validate_token' with the list of test accounts created
+            // Result gets included in the next tab
+            if (currentIndex === 2 && newIndex === 3)
+            {
+                form.steps("remove", 3);
+                form.steps("insert", 3, {
+                    title: "Get test accounts",
+                    contentMode: "async",
+                    contentUrl: "https://dev-edugain.renater.fr/accountmanager?action=validate_token&style=nobanner&sp_entityid="+
+                        encodeURIComponent($('#sp_entityid').val())+"&authentication_token="+encodeURIComponent($('#authentication_token').val())
+                });
+            }
+
             // Allways allow previous action even if the current form is not valid!
             if (currentIndex > newIndex)
             {
@@ -94,7 +107,7 @@ in eduGAIN inter-federation. Note that only a Service Provider administrator can
     
     <select  id="sp_entityid" name="sp_entityid" class="required">
         <option value="">Select your Service Provider below</option>
-        [% FOREACH entity IN federation_metadata_as_hashref %]
+        [% FOREACH entity IN federation_metadata_as_hashref.sort('entityid') %]
 <option value="[% entity.entityid %]">[% IF entity.display_name && entity.display_name.en %][% entity.display_name.en %] - [% END %][% entity.entityid %]</option>
         [% END %]
     </select>
diff --git a/templates/web/index-nobanner.tt2.html b/templates/web/index-nobanner.tt2.html
index 16dd4deecd630c45432d7f04d164ca1d43607b39..76fc3eef4e511e21e77e3754e28e011f6b522d22 100644
--- a/templates/web/index-nobanner.tt2.html
+++ b/templates/web/index-nobanner.tt2.html
@@ -4,4 +4,10 @@ Content-Type: text/html
 <?xml version="1.0" encoding="utf-8" ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/x
 html1/DTD/xhtml1-transitional.dtd">
 
+[% IF errors %]
+<div class="ui-widget">
+[% PROCESS 'templates/web/errors.tt2.html' %]
+</div>
+[% ELSE %]
 [% PROCESS 'templates/web/content.tt2.html' %]
+[% END %]
diff --git a/templates/web/validate_token.tt2.html b/templates/web/validate_token.tt2.html
new file mode 100644
index 0000000000000000000000000000000000000000..4d9bf0d9f6a294769c6d3720926108238695e12d
--- /dev/null
+++ b/templates/web/validate_token.tt2.html
@@ -0,0 +1,27 @@
+<h3>Get test accounts</h3>
+
+<div>
+Your identity has been checked successfully.
+
+Test accounts with different profiles have been created for you, see details below. Note that these accounts will automatically
+expire in [% conf.accounts_validity_period %] days. Note also that these test accounts can only be used to login on your SP [% sp_entityid %].
+
+<ol>
+    [% FOREACH test_account IN test_accounts %]
+    <li>account profile: [% test_account.get('account_profile') %]
+        <dl>    
+        <dd>user name: user[% test_account.get('id') %]</dd>
+        <dd>user password: [% test_account.get('user_password') %]</dd>
+        </dl>
+    </li>
+    [% END %]
+    
+</ol>
+
+You can now use these accounts to login at your federated service.
+To do so, you should select "[% conf.app_name %]" in your service discovery service menu.
+
+You should keep a record of these user names and passwords since we don't provide any mecanism to remind you the credentials. If
+you forget the credentials you can however ask for new test accounts via this service.
+
+Thank you for using the [% conf.app_name %]
\ No newline at end of file