Remove experimental_client_registration option
Change-Id: Ie8c7e80adabaaa73ebf26e5123e5ccfc639441bb
diff --git a/Changes b/Changes
index a9f0ce0..cf6c712 100755
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
-0.51 2023-05-16
+0.51 2023-06-09
- Support defined log file in configuration. (diewald)
+ - Remove experimental_client_registration setting
+ and make client registration mandatory in OAuth
+ (diewald)
0.50 2023-05-08
- Improvement of NKJP-annotation helper. (diewald)
diff --git a/lib/Kalamar/Plugin/Auth.pm b/lib/Kalamar/Plugin/Auth.pm
index 52d2560..ad3d4e4 100644
--- a/lib/Kalamar/Plugin/Auth.pm
+++ b/lib/Kalamar/Plugin/Auth.pm
@@ -971,25 +971,18 @@
)->name('logout');
+ # Add settings
+ $app->navi->add(settings => (
+ $app->loc('Auth_oauthSettings'), 'oauth'
+ ));
-
- # If "experimental_registration" is set, open
- # OAuth registration dialogues.
- if ($param->{experimental_client_registration}) {
-
- # Add settings
- $app->navi->add(settings => (
- $app->loc('Auth_oauthSettings'), 'oauth'
- )
- );
-
# $app->navi->add(settings => (
# $app->loc('Auth_marketplace'), 'marketplace'
# ));
- # Helper: Returns lists of registered plugins (of all users), which are permitted
- $app->helper(
+ # Helper: Returns lists of registered plugins (of all users), which are permitted
+ $app->helper(
'auth.plugin_list_p' => sub {
my $c = shift;
state $l_url = Mojo::URL->new($c->korap->api)->path('plugins');
@@ -998,41 +991,41 @@
super_client_secret => $client_secret,
#list only permitted plugins
permitted_only => 'true'
- })->then(
- sub {
- my $tx = shift;
- my $json = $tx->result->json;
- # Response is fine
- if ($tx->res->is_success) {
+ })->then(
+ sub {
+ my $tx = shift;
+ my $json = $tx->result->json;
+ # Response is fine
+ if ($tx->res->is_success) {
return Mojo::Promise->resolve($json);
};
- $c->log->error($tx->res->to_string);
+ $c->log->error($tx->res->to_string);
# Failure
$c->notify(error => $c->loc('Auth_responseError'));
return Mojo::Promise->reject($json // 'No response');
}
);
- }
- );
+ }
+ );
-
- #Helper: Returns list of all plugins, which are already installed
- $app->helper(
- 'auth.plugin_listin_p' => sub {
- my $c = shift;
- state $i_url = Mojo::URL->new($c->korap->api)->path('plugins/installed');
- return $c->korap_request(post => $i_url, {} => form => {
- super_client_id => $client_id,
- super_client_secret => $client_secret,
- })->then(
- sub {
- my $tx = shift;
- my $json = $tx->result->json;
- # Response is fine
- if ($tx->res->is_success) {
- return Mojo::Promise->resolve($json);
+
+ #Helper: Returns list of all plugins, which are already installed
+ $app->helper(
+ 'auth.plugin_listin_p' => sub {
+ my $c = shift;
+ state $i_url = Mojo::URL->new($c->korap->api)->path('plugins/installed');
+ return $c->korap_request(post => $i_url, {} => form => {
+ super_client_id => $client_id,
+ super_client_secret => $client_secret,
+ })->then(
+ sub {
+ my $tx = shift;
+ my $json = $tx->result->json;
+ # Response is fine
+ if ($tx->res->is_success) {
+ return Mojo::Promise->resolve($json);
};
-
+
$c->log->error($tx->res->to_string);
# Failure
@@ -1040,28 +1033,28 @@
return Mojo::Promise->reject($json // 'No response');
}
);
- }
- );
+ }
+ );
- # Route to marketplace (for installation and deinstallation of plugins)
- $r->get('/settings/marketplace')->to(
- cb => sub {
- my $c = shift;
- _set_no_cache($c->res->headers);
- unless ($c->auth->token) {
- return $c->render(
- template => 'exception',
- msg => $c->loc('Auth_authenticationFail'),
- status => 401
- );
- };
+ # Route to marketplace (for installation and deinstallation of plugins)
+ $r->get('/settings/marketplace')->to(
+ cb => sub {
+ my $c = shift;
+ _set_no_cache($c->res->headers);
+ unless ($c->auth->token) {
+ return $c->render(
+ template => 'exception',
+ msg => $c->loc('Auth_authenticationFail'),
+ status => 401
+ );
+ };
- $c->render_later;
+ $c->render_later;
my $promiselist = $c->auth->plugin_list_p;
my $promiseinlist = $c->auth->plugin_listin_p;
Mojo::Promise->all($promiselist, $promiseinlist)-> then(
- sub {
+ sub {
my ($promiselist, $promiseinlist) = @_;
my $plist = ref($promiselist->[0]) eq 'ARRAY' ? $promiselist->[0] : [];
my $plinlist = ref($promiseinlist->[0]) eq 'ARRAY' ? $promiseinlist->[0] : [];
@@ -1070,614 +1063,607 @@
if($plinlist){
foreach my $entry (@$plinlist){
@$clean_pllist = grep{!($_->{client_id} eq $entry->{client_id})} @$clean_pllist ;
- }
}
- $c->stash('plugin_list', $clean_pllist);
}
- )
- ->catch(
- sub {
- return;
- }
- )
- ->finally(
- sub {
- return $c->render(template => 'auth/marketplace');
- }
- )->wait;
- }
- )->name('marketplace');
+ $c->stash('plugin_list', $clean_pllist);
+ }
+ )->catch(
+ sub {
+ return;
+ }
+ )->finally(
+ sub {
+ return $c->render(template => 'auth/marketplace');
+ }
+ )->wait;
+ }
+ )->name('marketplace');
+ # Route to install plugin
+ $r->post('/settings/marketplace')->to(
+ cb => sub {
+ my $c = shift;
+ _set_no_cache($c->res->headers);
+ my $v = $c->validation;
+ $v->required('client-id');
- # Route to install plugin
- $r->post('/settings/marketplace')->to(
- cb => sub {
- my $c = shift;
- _set_no_cache($c->res->headers);
- my $v = $c->validation;
- $v->required('client-id');
-
- if ($v->has_error) {
- return $c->render(
+ if ($v->has_error) {
+ return $c->render(
json => [],
status => 400
- );
- };
-
- unless ($c->auth->token) {
- return $c->render(
+ );
+ };
+
+ unless ($c->auth->token) {
+ return $c->render(
content => 'Unauthorized',
status => 401
- );
- };
-
- my $mclient_id = $v->param('client-id');
- $c->render_later;
-
- state $p_url = Mojo::URL->new($c->korap->api)->path('plugins/install');
-
- return $c->korap_request(post => $p_url, {} => form => {
- super_client_id => $client_id,
- super_client_secret => $client_secret,
- client_id => $mclient_id
- })->then(
- sub {
- my $tx = shift;
- my $json = $tx->result->json;
- # Response is fine
- if ($tx->res->is_success) {
- return Mojo::Promise->resolve($json);
- };
- #Log errors
- $c->log->error($tx->res->to_string);
- # Failure
- return Mojo::Promise->reject;
- }
- )
-
- ->catch(
- sub {
- $c->notify('error' => $c->loc('Auth_installFail'));
- }
- )
- ->finally(
- sub {
- return $c->redirect_to('marketplace');
- }
);
- }
- )->name('install-plugin');
+ };
+ my $mclient_id = $v->param('client-id');
+ $c->render_later;
- # Route to OAuth settings
- $r->get('/settings/oauth')->to(
- cb => sub {
- my $c = shift;
+ state $p_url = Mojo::URL->new($c->korap->api)->path('plugins/install');
- _set_no_cache($c->res->headers);
-
- unless ($c->auth->token) {
- return $c->render(
- template => 'exception',
- msg => $c->loc('Auth_authenticationFail'),
- status => 401
- );
- };
-
- # Wait for async result
- $c->render_later;
-
- $c->auth->client_list_p->then(
- sub {
- $c->stash('client_list' => shift);
- }
- )->catch(
- sub {
- return;
- }
- )->finally(
- sub {
- return $c->render(template => 'auth/clients')
- }
- );
- }
- )->name('oauth-settings');
-
- # Route to oauth client registration
- $r->post('/settings/oauth/register')->to(
- cb => sub {
- my $c = shift;
-
- _set_no_cache($c->res->headers);
-
- my $v = $c->validation;
-
- unless ($c->auth->token) {
- return $c->render(
- content => 'Unauthorized',
- status => 401
- );
- };
-
- $v->csrf_protect;
- $v->required('name', 'trim', 'not_empty')->size(3, 255);
- $v->required('type')->in('PUBLIC', 'CONFIDENTIAL');
- $v->required('desc', 'trim', 'not_empty')->size(3, 255);
- $v->optional('url', 'trim', 'not_empty')->like(qr/^(http|$)/i);
- $v->optional('redirect_uri', 'trim', 'not_empty')->like(qr/^(http|$)/i);
- $v->optional('src', 'not_empty');
-
- $c->stash(template => 'auth/clients');
-
- # Render with error
- if ($v->has_error) {
- if ($v->has_error('csrf_token')) {
- $c->notify(error => $c->loc('Auth_csrfFail'));
- }
- else {
- $c->notify(error => $c->loc('Auth_paramError'));
+ return $c->korap_request(post => $p_url, {} => form => {
+ super_client_id => $client_id,
+ super_client_secret => $client_secret,
+ client_id => $mclient_id
+ })->then(
+ sub {
+ my $tx = shift;
+ my $json = $tx->result->json;
+ # Response is fine
+ if ($tx->res->is_success) {
+ return Mojo::Promise->resolve($json);
};
+ #Log errors
+ $c->log->error($tx->res->to_string);
+ # Failure
+ return Mojo::Promise->reject;
+ }
+ )->catch(
+ sub {
+ $c->notify('error' => $c->loc('Auth_installFail'));
+ }
+ )->finally(
+ sub {
+ return $c->redirect_to('marketplace');
+ }
+ );
+ }
+ )->name('install-plugin');
+
+
+ # Route to OAuth settings
+ $r->get('/settings/oauth')->to(
+ cb => sub {
+ my $c = shift;
+
+ _set_no_cache($c->res->headers);
+
+ unless ($c->auth->token) {
+ return $c->render(
+ template => 'exception',
+ msg => $c->loc('Auth_authenticationFail'),
+ status => 401
+ );
+ };
+
+ # Wait for async result
+ $c->render_later;
+
+ $c->auth->client_list_p->then(
+ sub {
+ $c->stash('client_list' => shift);
+ }
+ )->catch(
+ sub {
+ return;
+ }
+ )->finally(
+ sub {
+ return $c->render(template => 'auth/clients')
+ }
+ );
+ }
+ )->name('oauth-settings');
+
+ # Route to oauth client registration
+ $r->post('/settings/oauth/register')->to(
+ cb => sub {
+ my $c = shift;
+
+ _set_no_cache($c->res->headers);
+
+ my $v = $c->validation;
+
+ unless ($c->auth->token) {
+ return $c->render(
+ content => 'Unauthorized',
+ status => 401
+ );
+ };
+
+ $v->csrf_protect;
+ $v->required('name', 'trim', 'not_empty')->size(3, 255);
+ $v->required('type')->in('PUBLIC', 'CONFIDENTIAL');
+ $v->required('desc', 'trim', 'not_empty')->size(3, 255);
+ $v->optional('url', 'trim', 'not_empty')->like(qr/^(http|$)/i);
+ $v->optional('redirect_uri', 'trim', 'not_empty')->like(qr/^(http|$)/i);
+ $v->optional('src', 'not_empty');
+
+ $c->stash(template => 'auth/clients');
+
+ # Render with error
+ if ($v->has_error) {
+ if ($v->has_error('csrf_token')) {
+ $c->notify(error => $c->loc('Auth_csrfFail'));
+ }
+ else {
+ $c->notify(error => $c->loc('Auth_paramError'));
+ };
+ return $c->render;
+ } elsif ($c->req->is_limit_exceeded) {
+ $c->notify(error => $c->loc('Auth_fileSizeExceeded'));
+ return $c->render;
+ };
+
+ my $type = $v->param('type');
+ my $src = $v->param('src');
+ my $src_json;
+
+ my $json_obj = {
+ name => $v->param('name'),
+ type => $type,
+ description => $v->param('desc'),
+ url => $v->param('url'),
+ redirect_uri => $v->param('redirect_uri')
+ };
+
+ # Check plugin source
+ if ($src) {
+
+ # Source need to be a file upload
+ if (!ref $src || !$src->isa('Mojo::Upload')) {
+ $c->notify(error => $c->loc('Auth_jsonRequired'));
return $c->render;
- } elsif ($c->req->is_limit_exceeded) {
+ };
+
+ # Uploads can't be too large
+ if ($src->size > 1_000_000) {
$c->notify(error => $c->loc('Auth_fileSizeExceeded'));
return $c->render;
};
- my $type = $v->param('type');
- my $src = $v->param('src');
- my $src_json;
+ # Check upload is not empty
+ if ($src->size > 0 && $src->filename ne '') {
- my $json_obj = {
- name => $v->param('name'),
- type => $type,
- description => $v->param('desc'),
- url => $v->param('url'),
- redirect_uri => $v->param('redirect_uri')
- };
+ # Plugins need to be confidential
+ if ($type ne 'CONFIDENTIAL') {
+ $c->notify(error => $c->loc('Auth_confidentialRequired'));
+ return $c->render;
+ };
- # Check plugin source
- if ($src) {
+ my $asset = $src->asset;
- # Source need to be a file upload
- if (!ref $src || !$src->isa('Mojo::Upload')) {
+ # Check for json
+ eval {
+ $src_json = decode_json($asset->slurp);
+ };
+
+ if ($@ || !ref $src_json || ref $src_json ne 'HASH') {
$c->notify(error => $c->loc('Auth_jsonRequired'));
return $c->render;
};
- # Uploads can't be too large
- if ($src->size > 1_000_000) {
- $c->notify(error => $c->loc('Auth_fileSizeExceeded'));
- return $c->render;
- };
-
- # Check upload is not empty
- if ($src->size > 0 && $src->filename ne '') {
-
- # Plugins need to be confidential
- if ($type ne 'CONFIDENTIAL') {
- $c->notify(error => $c->loc('Auth_confidentialRequired'));
- return $c->render;
- }
-
- my $asset = $src->asset;
-
- # Check for json
- eval {
- $src_json = decode_json($asset->slurp);
- };
-
- if ($@ || !ref $src_json || ref $src_json ne 'HASH') {
- $c->notify(error => $c->loc('Auth_jsonRequired'));
- return $c->render;
- };
-
- $json_obj->{source} = $src_json;
- };
+ $json_obj->{source} = $src_json;
};
+ };
- # Wait for async result
- $c->render_later;
+ # Wait for async result
+ $c->render_later;
- # Register on server
- state $url = Mojo::URL->new($c->korap->api)->path('oauth2/client/register');
- $c->korap_request('POST', $url => {} => json => $json_obj)->then(
- sub {
- my $tx = shift;
- my $result = $tx->result;
+ # Register on server
+ state $url = Mojo::URL->new($c->korap->api)->path('oauth2/client/register');
+ $c->korap_request('POST', $url => {} => json => $json_obj)->then(
+ sub {
+ my $tx = shift;
+ my $result = $tx->result;
- if ($result->is_error) {
- my $json = $result->json;
- if ($json && $json->{error}) {
- $c->notify(
- error => $json->{error} .
- ($json->{error_description} ? ': ' . $json->{error_description} : '')
- )
- };
-
- return Mojo::Promise->reject;
- };
-
+ if ($result->is_error) {
my $json = $result->json;
-
- my $client_id = $json->{client_id};
- my $client_secret = $json->{client_secret};
-
- $c->stash('client_name' => $v->param('name'));
- $c->stash('client_desc' => $v->param('desc'));
- $c->stash('client_type' => $v->param('type'));
- $c->stash('client_url' => $v->param('url'));
- $c->stash('client_src' => $v->param('source'));
- $c->stash('client_redirect_uri' => $v->param('redirect_uri'));
- $c->stash('client_id' => $client_id);
-
- if ($client_secret) {
- $c->stash('client_secret' => $client_secret);
+ if ($json && $json->{error}) {
+ $c->notify(
+ error => $json->{error} .
+ ($json->{error_description} ? ': ' . $json->{error_description} : '')
+ )
};
- $c->notify(success => $c->loc('Auth_en_registerSuccess'));
+ return Mojo::Promise->reject;
+ };
- return $c->render(template => 'auth/client');
- }
- )->catch(
- sub {
- $c->notify('error' => $c->loc('Auth_en_registerFail'));
- }
- )->finally(
- sub {
- return $c->redirect_to('settings' => { scope => 'oauth' });
- }
+ my $json = $result->json;
+
+ my $client_id = $json->{client_id};
+ my $client_secret = $json->{client_secret};
+
+ $c->stash('client_name' => $v->param('name'));
+ $c->stash('client_desc' => $v->param('desc'));
+ $c->stash('client_type' => $v->param('type'));
+ $c->stash('client_url' => $v->param('url'));
+ $c->stash('client_src' => $v->param('source'));
+ $c->stash('client_redirect_uri' => $v->param('redirect_uri'));
+ $c->stash('client_id' => $client_id);
+
+ if ($client_secret) {
+ $c->stash('client_secret' => $client_secret);
+ };
+
+ $c->notify(success => $c->loc('Auth_en_registerSuccess'));
+
+ return $c->render(template => 'auth/client');
+ }
+ )->catch(
+ sub {
+ $c->notify('error' => $c->loc('Auth_en_registerFail'));
+ }
+ )->finally(
+ sub {
+ return $c->redirect_to('settings' => { scope => 'oauth' });
+ }
+ );
+ }
+ )->name('oauth-register');
+
+
+ # Unregister client page
+ $r->get('/settings/oauth/:client_id/unregister')->to(
+ cb => sub {
+ my $c = shift;
+ _set_no_cache($c->res->headers);
+ $c->render(template => 'auth/unregister');
+ }
+ )->name('oauth-unregister');
+
+
+ # Unregister client
+ $r->post('/settings/oauth/:client_id/unregister')->to(
+ cb => sub {
+ my $c = shift;
+ _set_no_cache($c->res->headers);
+
+ my $v = $c->validation;
+
+ unless ($c->auth->token) {
+ return $c->render(
+ content => 'Unauthorized',
+ status => 401
);
- }
- )->name('oauth-register');
+ };
+ $v->csrf_protect;
+ $v->required('client-name', 'trim')->size(3, 255);
- # Unregister client page
- $r->get('/settings/oauth/:client_id/unregister')->to(
- cb => sub {
- my $c = shift;
- _set_no_cache($c->res->headers);
- $c->render(template => 'auth/unregister');
- }
- )->name('oauth-unregister');
-
-
- # Unregister client
- $r->post('/settings/oauth/:client_id/unregister')->to(
- cb => sub {
- my $c = shift;
- _set_no_cache($c->res->headers);
-
- my $v = $c->validation;
-
- unless ($c->auth->token) {
- return $c->render(
- content => 'Unauthorized',
- status => 401
- );
+ # Render with error
+ if ($v->has_error) {
+ if ($v->has_error('csrf_token')) {
+ $c->notify(error => $c->loc('Auth_csrfFail'));
+ }
+ else {
+ $c->notify(error => $c->loc('Auth_paramError'));
};
+ return $c->redirect_to('oauth-settings');
+ };
- $v->csrf_protect;
- $v->required('client-name', 'trim')->size(3, 255);
+ my $client_id = $c->stash('client_id');
+ my $client_name = $v->param('client-name');
+ my $client_secret = $v->param('client-secret');
- # Render with error
- if ($v->has_error) {
- if ($v->has_error('csrf_token')) {
- $c->notify(error => $c->loc('Auth_csrfFail'));
+ # Get list of registered clients
+ my $r_url = Mojo::URL->new($c->korap->api)->path('oauth2/client/deregister/')->path(
+ $client_id
+ );
+
+ my $send = {};
+
+ if ($client_secret) {
+ $send->{client_secret} = $client_secret;
+ };
+
+ # Get the list of all clients
+ return $c->korap_request(delete => $r_url, {} => form => $send)->then(
+ sub {
+ my $tx = shift;
+
+ # Response is fine
+ if ($tx->res->is_success) {
+ # Okay
+ $c->notify(success => 'Successfully deleted ' . $client_name);
}
else {
- $c->notify(error => $c->loc('Auth_paramError'));
+
+ # Failure
+ my $json = $tx->result->json;
+ if ($json && $json->{error_description}) {
+ $c->notify(error => $json->{error_description});
+ } else {
+ $c->notify(error => $c->loc('Auth_responseError'));
+ };
};
+
return $c->redirect_to('oauth-settings');
+ }
+ );
+ }
+ )->name('oauth-unregister-post');
+
+
+ # OAuth Client authorization
+ $r->get('/settings/oauth/authorize')->to(
+ cb => sub {
+ my $c = shift;
+
+ _set_no_cache($c->res->headers);
+
+ my $v = $c->validation;
+ $v->required('client_id', 'trim');
+ $v->required('scope', 'trim');
+ $v->optional('state', 'trim');
+ $v->optional('redirect_uri', 'trim', 'not_empty')->like(qr/^(http|$)/i);
+
+ # Redirect with error
+ if ($v->has_error) {
+
+ if ($v->has_error('client_id')) {
+ $c->notify(error => $c->loc('Auth_clientIDFail'));
+ }
+ elsif ($v->has_error('scope')) {
+ $c->notify(error => $c->loc('Auth_scopeFail'));
+ }
+ else {
+ $c->notify(error => $c->loc('Auth_paramError'));
};
- my $client_id = $c->stash('client_id');
- my $client_name = $v->param('client-name');
- my $client_secret = $v->param('client-secret');
+ # If logged in, go to oauth settings - otherwise to index
+ return $c->redirect_to($c->auth->token ? 'oauth-settings' : 'index');
+ };
- # Get list of registered clients
- my $r_url = Mojo::URL->new($c->korap->api)->path('oauth2/client/deregister/')->path(
- $client_id
- );
+ foreach (qw!scope client_id state redirect_uri!) {
+ $c->stash($_, $v->param($_));
+ };
- my $send = {};
+ # Wait for async result
+ $c->render_later;
- if ($client_secret) {
- $send->{client_secret} = $client_secret;
- };
+ my $client_id = $v->param('client_id');
- # Get the list of all clients
- return $c->korap_request(delete => $r_url, {} => form => $send)->then(
- sub {
- my $tx = shift;
+ my $client_information = $c->auth->client_info_p($client_id)->then(
+ sub {
+ my $cl = shift;
+ $c->stash(client_name => $cl->{'client_name'});
+ $c->stash(client_type => $cl->{'client_type'});
+ $c->stash(client_desc => $cl->{'client_description'});
+ $c->stash(client_url => $cl->{'client_url'});
+ $c->stash(redirect_uri_server => $cl->{'client_redirect_uri'});
+ }
+ )->then(
+ sub {
- # Response is fine
- if ($tx->res->is_success) {
- # Okay
- $c->notify(success => 'Successfully deleted ' . $client_name);
+ # Check, if the client redirect_uri is valid
+ my $redirect_uri_server = $c->stash('redirect_uri_server');
+ my $redirect_uri = $v->param('redirect_uri');
+ my ($server_o, $client_o);
+
+ # Both exist
+ if ($redirect_uri_server && $redirect_uri) {
+ $server_o = Mojo::URL->new($redirect_uri_server);
+ $client_o = Mojo::URL->new($redirect_uri);
+
+ # Host not valid - take registered URI
+ if ($server_o->host ne $client_o->host) {
+ $c->notify(warn => 'redirect_uri host differs from registered host');
+ $client_o = $server_o;
}
- else {
- # Failure
- my $json = $tx->result->json;
- if ($json && $json->{error_description}) {
- $c->notify(error => $json->{error_description});
- } else {
- $c->notify(error => $c->loc('Auth_responseError'));
- };
+ # Port not valid - take registered URI
+ elsif (($server_o->port // '') ne ($client_o->port // '')) {
+ $c->notify(warn => 'redirect_uri port differs from registered port');
+ $client_o = $server_o;
};
-
- return $c->redirect_to('oauth-settings');
}
- );
- }
- )->name('oauth-unregister-post');
-
- # OAuth Client authorization
- $r->get('/settings/oauth/authorize')->to(
- cb => sub {
- my $c = shift;
-
- _set_no_cache($c->res->headers);
-
- my $v = $c->validation;
- $v->required('client_id', 'trim');
- $v->required('scope', 'trim');
- $v->optional('state', 'trim');
- $v->optional('redirect_uri', 'trim', 'not_empty')->like(qr/^(http|$)/i);
-
- # Redirect with error
- if ($v->has_error) {
-
- if ($v->has_error('client_id')) {
- $c->notify(error => $c->loc('Auth_clientIDFail'));
+ # Client sent exists
+ elsif ($redirect_uri) {
+ $client_o = Mojo::URL->new($redirect_uri);
+ $c->stash(redirect_warning => $c->loc('oauthGrantRedirectWarn'))
}
- elsif ($v->has_error('scope')) {
- $c->notify(error => $c->loc('Auth_scopeFail'));
+
+ # Server registered exists
+ elsif ($redirect_uri_server) {
+ $client_o = Mojo::URL->new($redirect_uri_server);
}
+
+ # Redirect unknown
else {
- $c->notify(error => $c->loc('Auth_paramError'));
- };
-
- # If logged in, go to oauth settings - otherwise to index
- return $c->redirect_to($c->auth->token ? 'oauth-settings' : 'index');
- };
-
- foreach (qw!scope client_id state redirect_uri!) {
- $c->stash($_, $v->param($_));
- };
-
- # Wait for async result
- $c->render_later;
-
- my $client_id = $v->param('client_id');
-
- my $client_information = $c->auth->client_info_p($client_id)->then(
- sub {
- my $cl = shift;
- $c->stash(client_name => $cl->{'client_name'});
- $c->stash(client_type => $cl->{'client_type'});
- $c->stash(client_desc => $cl->{'client_description'});
- $c->stash(client_url => $cl->{'client_url'});
- $c->stash(redirect_uri_server => $cl->{'client_redirect_uri'});
- }
- )->then(
- sub {
-
- # Check, if the client redirect_uri is valid
- my $redirect_uri_server = $c->stash('redirect_uri_server');
- my $redirect_uri = $v->param('redirect_uri');
- my ($server_o, $client_o);
-
- # Both exist
- if ($redirect_uri_server && $redirect_uri) {
- $server_o = Mojo::URL->new($redirect_uri_server);
- $client_o = Mojo::URL->new($redirect_uri);
-
- # Host not valid - take registered URI
- if ($server_o->host ne $client_o->host) {
- $c->notify(warn => 'redirect_uri host differs from registered host');
- $client_o = $server_o;
- }
-
- # Port not valid - take registered URI
- elsif (($server_o->port // '') ne ($client_o->port // '')) {
- $c->notify(warn => 'redirect_uri port differs from registered port');
- $client_o = $server_o;
- };
- }
-
- # Client sent exists
- elsif ($redirect_uri) {
- $client_o = Mojo::URL->new($redirect_uri);
- $c->stash(redirect_warning => $c->loc('oauthGrantRedirectWarn'))
- }
-
- # Server registered exists
- elsif ($redirect_uri_server) {
- $client_o = Mojo::URL->new($redirect_uri_server);
- }
-
- # Redirect unknown
- else {
- $c->notify(error => 'redirect_uri not set');
-
- # If logged in, go to oauth settings - otherwise to index
- return $c->redirect_to($c->auth->token ? 'oauth-settings' : 'index');
- };
-
- # No userinfo allowed
- if ($client_o->userinfo) {
- $c->notify(warn => 'redirect_uri contains userinfo');
- $client_o->userinfo('');
- };
-
- # HTTPS warning
- # if ($client_o->scheme ne 'https') {
- # $c->notify(warn => 'redirect_uri is not HTTPS');
- # };
-
- # Sign redirection URL
- $c->stash(redirect_uri => $client_o->to_string);
- $c->stash(close_redirect_uri => '' . $c->close_redirect_to($client_o));
-
- # Get auth token
- my $auth_token = $c->auth->token;
-
- # User is not logged in - log in before!
- unless ($auth_token) {
- return $c->render(template => 'auth/login');
- };
-
- # Grant authorization
- return $c->render(template => 'auth/grant_scope');
- }
- )->catch(
- sub {
- my $error = shift;
- $c->notify(error => $error);
+ $c->notify(error => 'redirect_uri not set');
# If logged in, go to oauth settings - otherwise to index
return $c->redirect_to($c->auth->token ? 'oauth-settings' : 'index');
- }
- );
- }
- )->name('oauth-grant-scope');
-
-
- # OAuth Client authorization
- # This will return a location information including some info
- $r->post('/settings/oauth/authorize')->to(
- cb => sub {
- my $c = shift;
-
- _set_no_cache($c->res->headers);
-
- # It's necessary that it's clear this was triggered by
- # KorAP and not by the client!
- my $v = $c->validation;
- $v->csrf_protect;
- $v->required('client_id', 'trim');
- $v->required('scope', 'trim');
- $v->optional('state', 'trim');
-
- # Only signed redirects are allowed
- $v->required('redirect_uri', 'trim', 'not_empty')->closed_redirect;
-
- # Render with error
- if ($v->has_error) {
-
- # If logged in, go to oauth settings - otherwise to index
- my $url = $c->url_for($c->auth->token ? 'oauth-settings' : 'index');
-
- if ($v->has_error('client_id')) {
- $url->query([error_description => $c->loc('Auth_clientIDFail')]);
- }
- elsif ($v->has_error('scope')) {
- $url->query([error_description => $c->loc('Auth_scopeFail')]);
- }
- elsif ($v->has_error('csrf_token')) {
- $url->query([error_description => $c->loc('Auth_csrfFail')]);
- }
- else {
- $url->query([error_description => $c->loc('Auth_paramError')]);
};
- return $c->redirect_to($url);
+ # No userinfo allowed
+ if ($client_o->userinfo) {
+ $c->notify(warn => 'redirect_uri contains userinfo');
+ $client_o->userinfo('');
+ };
+
+ # HTTPS warning
+ # if ($client_o->scheme ne 'https') {
+ # $c->notify(warn => 'redirect_uri is not HTTPS');
+ # };
+
+ # Sign redirection URL
+ $c->stash(redirect_uri => $client_o->to_string);
+ $c->stash(close_redirect_uri => '' . $c->close_redirect_to($client_o));
+
+ # Get auth token
+ my $auth_token = $c->auth->token;
+
+ # User is not logged in - log in before!
+ unless ($auth_token) {
+ return $c->render(template => 'auth/login');
+ };
+
+ # Grant authorization
+ return $c->render(template => 'auth/grant_scope');
+ }
+ )->catch(
+ sub {
+ my $error = shift;
+ $c->notify(error => $error);
+
+ # If logged in, go to oauth settings - otherwise to index
+ return $c->redirect_to($c->auth->token ? 'oauth-settings' : 'index');
+ }
+ );
+ }
+ )->name('oauth-grant-scope');
+
+
+ # OAuth Client authorization
+ # This will return a location information including some info
+ $r->post('/settings/oauth/authorize')->to(
+ cb => sub {
+ my $c = shift;
+
+ _set_no_cache($c->res->headers);
+
+ # It's necessary that it's clear this was triggered by
+ # KorAP and not by the client!
+ my $v = $c->validation;
+ $v->csrf_protect;
+ $v->required('client_id', 'trim');
+ $v->required('scope', 'trim');
+ $v->optional('state', 'trim');
+
+ # Only signed redirects are allowed
+ $v->required('redirect_uri', 'trim', 'not_empty')->closed_redirect;
+
+ # Render with error
+ if ($v->has_error) {
+
+ # If logged in, go to oauth settings - otherwise to index
+ my $url = $c->url_for($c->auth->token ? 'oauth-settings' : 'index');
+
+ if ($v->has_error('client_id')) {
+ $url->query([error_description => $c->loc('Auth_clientIDFail')]);
+ }
+ elsif ($v->has_error('scope')) {
+ $url->query([error_description => $c->loc('Auth_scopeFail')]);
+ }
+ elsif ($v->has_error('csrf_token')) {
+ $url->query([error_description => $c->loc('Auth_csrfFail')]);
+ }
+ else {
+ $url->query([error_description => $c->loc('Auth_paramError')]);
};
- $c->stash(redirect_uri => Mojo::URL->new($v->param('redirect_uri')));
+ return $c->redirect_to($url);
+ };
- return $c->auth->new_token_p(
- client_id => $v->param('client_id'),
- redirect_uri => $c->stash('redirect_uri'),
- state => $v->param('state'),
- scope => $v->param('scope'),
- )->catch(
- sub {
- my $err_msg = shift;
- my $url = $c->stash('redirect_uri');
+ $c->stash(redirect_uri => Mojo::URL->new($v->param('redirect_uri')));
- # Redirect!
- if ($url) {
- if ($err_msg) {
- $url = $url->query([error_description => $err_msg]);
- };
- }
+ return $c->auth->new_token_p(
+ client_id => $v->param('client_id'),
+ redirect_uri => $c->stash('redirect_uri'),
+ state => $v->param('state'),
+ scope => $v->param('scope'),
+ )->catch(
+ sub {
+ my $err_msg = shift;
+ my $url = $c->stash('redirect_uri');
- # Do not redirect!
- else {
- $c->notify(error => $err_msg);
-
- # If logged in, go to oauth settings - otherwise to index
- $url = $c->url_for($c->auth->token ? 'oauth-settings' : 'index');
+ # Redirect!
+ if ($url) {
+ if ($err_msg) {
+ $url = $url->query([error_description => $err_msg]);
};
-
- return Mojo::Promise->resolve($url);
}
- )->then(
- sub {
- my $loc = shift;
- return $c->redirect_to($loc);
- }
- )->wait;
- return $c->rendered;
- }
- )->name('oauth-grant-scope-post');
+
+ # Do not redirect!
+ else {
+ $c->notify(error => $err_msg);
+
+ # If logged in, go to oauth settings - otherwise to index
+ $url = $c->url_for($c->auth->token ? 'oauth-settings' : 'index');
+ };
+
+ return Mojo::Promise->resolve($url);
+ }
+ )->then(
+ sub {
+ my $loc = shift;
+ return $c->redirect_to($loc);
+ }
+ )->wait;
+ return $c->rendered;
+ }
+ )->name('oauth-grant-scope-post');
- # Show information of a client
- $r->get('/settings/oauth/:client_id')->to(
- cb => sub {
- my $c = shift;
+ # Show information of a client
+ $r->get('/settings/oauth/:client_id')->to(
+ cb => sub {
+ my $c = shift;
- _set_no_cache($c->res->headers);
+ _set_no_cache($c->res->headers);
- $c->render_later;
+ $c->render_later;
- $c->auth->client_list_p->then(
- sub {
- my $json = shift;
+ $c->auth->client_list_p->then(
+ sub {
+ my $json = shift;
- my ($item) = grep {
- $c->stash('client_id') eq $_->{client_id}
- } @$json;
+ my ($item) = grep {
+ $c->stash('client_id') eq $_->{client_id}
+ } @$json;
- unless ($item) {
- return Mojo::Promise->reject;
- };
+ unless ($item) {
+ return Mojo::Promise->reject;
+ };
- $c->stash(client_name => $item->{client_name});
- $c->stash(client_desc => $item->{client_description});
- $c->stash(client_url => $item->{client_url});
- $c->stash(client_type => ($item->{client_type} // 'PUBLIC'));
- $c->stash(client_redirect_uri => $item->{client_redirect_uri});
- $c->stash(client_src => encode_json($item->{source})) if $item->{source};
+ $c->stash(client_name => $item->{client_name});
+ $c->stash(client_desc => $item->{client_description});
+ $c->stash(client_url => $item->{client_url});
+ $c->stash(client_type => ($item->{client_type} // 'PUBLIC'));
+ $c->stash(client_redirect_uri => $item->{client_redirect_uri});
+ $c->stash(client_src => encode_json($item->{source})) if $item->{source};
- $c->auth->token_list_p($c->stash('client_id'));
- }
- )->then(
- sub {
- my $json = shift;
+ $c->auth->token_list_p($c->stash('client_id'));
+ }
+ )->then(
+ sub {
+ my $json = shift;
- $c->stash(tokens => $json);
+ $c->stash(tokens => $json);
- return Mojo::Promise->resolve;
- }
- )->catch(
- sub {
- return $c->reply->not_found;
- }
- )->finally(
- sub {
- return $c->render(template => 'auth/client')
- }
- );
+ return Mojo::Promise->resolve;
+ }
+ )->catch(
+ sub {
+ return $c->reply->not_found;
+ }
+ )->finally(
+ sub {
+ return $c->render(template => 'auth/client')
+ }
+ );
- return;
- }
- )->name('oauth-tokens');
- };
+ return;
+ }
+ )->name('oauth-tokens');
# Ask if new token should be issued