Support client_file parameter as an alternative to client_id and client_secret

Change-Id: I423fa81c7ad3c9121973688346070cb7670afdbb
diff --git a/Changes b/Changes
index fc20a0c..0fc3240 100755
--- a/Changes
+++ b/Changes
@@ -1,5 +1,7 @@
 0.47 2022-11-22
         - Add command to generate super_client_info file. (diewald)
+        - Support 'client_file' parameter as an alternative to 'client_id'
+          and 'client_secret'. (diewald)
 
 0.46 2022-08-08
         - Increased max query length from 1000 to 4096 characters. (kupietz)
diff --git a/lib/Kalamar/Plugin/Auth.pm b/lib/Kalamar/Plugin/Auth.pm
index dcc6bda..5843929 100644
--- a/lib/Kalamar/Plugin/Auth.pm
+++ b/lib/Kalamar/Plugin/Auth.pm
@@ -3,6 +3,7 @@
 use File::Basename 'dirname';
 use File::Spec::Functions qw/catdir/;
 use Mojo::ByteStream 'b';
+use Mojo::File qw!path!;
 use Mojo::Util qw!b64_encode encode!;
 use Mojo::JSON qw'decode_json encode_json';
 use Encode 'is_utf8';
@@ -52,6 +53,13 @@
     $_->default_expiration(60*60*24*3); # Session expires after 3 days of non-use
   };
 
+  # Get client_id and client_secret from client file
+  if ($param->{client_file}) {
+    my $client_json = decode_json(path($param->{client_file})->slurp);
+    $param->{client_id} //= $client_json->{client_id};
+    $param->{client_secret} //= $client_json->{client_secret};
+  };
+
   # Get the client id and the client_secret as a requirement
   unless ($param->{client_id} && $param->{client_secret}) {
     $app->log->error('client_id or client_secret not defined');
diff --git a/t/plugin/auth-oauth.t b/t/plugin/auth-oauth.t
index 03a3c1c..a2b2039 100644
--- a/t/plugin/auth-oauth.t
+++ b/t/plugin/auth-oauth.t
@@ -2,7 +2,7 @@
 use Test::More;
 use Mojo::ByteStream 'b';
 use Test::Mojo::WithRoles 'Session';
-use Mojo::File qw/path/;
+use Mojo::File qw/path tempfile/;
 use Data::Dumper;
 
 
@@ -955,6 +955,56 @@
   ;
 
 
+# Retest client with super_client_file
+my $client_file = tempfile;
+
+$client_file->spurt(
+  '{"client_id":"2","client_secret":"k414m4r-s3cr3t"}'
+);
+
+$t = Test::Mojo::WithRoles->new('Kalamar' => {
+  Kalamar => {
+    plugins => ['Auth']
+  },
+  'Kalamar-Auth' => {
+    client_file => $client_file,
+    oauth2 => 1
+  }
+});
+
+$t->app->plugin(
+  Mount => {
+    $mount_point =>
+      $fixtures_path->child('mock.pl')
+  }
+);
+
+$csrf = $t->get_ok('/')
+  ->status_is(200)
+  ->element_exists_not('div.button.top a')
+  ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
+  ;
+
+$t->post_ok('/user/login' => form => {
+  handle_or_email => 'test',
+  pwd => 'pass',
+  csrf_token => $csrf
+})
+  ->status_is(302)
+  ->header_is('Location' => '/')
+  ->content_is('');
+
+$t->get_ok('/')
+  ->status_is(200)
+  ->element_exists_not('div.notify-error')
+  ->element_exists('div.notify-success')
+  ->text_is('div.notify-success', 'Login successful')
+  ->element_exists_not('aside.off')
+  ->element_exists_not('aside.active')
+  ->element_exists('aside.settings')
+  ;
+
+
 done_testing;
 __END__