Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better error handling for OIDC warmup errors, resolves #77 #78

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions lib/Mojolicious/Plugin/OAuth2.pm
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ sub _auth_url {
$authorize_url = Mojo::URL->new($provider_args->{authorize_url});
$authorize_url->host($args->{host}) if exists $args->{host};
$authorize_url->query->append(client_id => $provider_args->{key}, redirect_uri => $args->{redirect_uri});
$authorize_url->query->append(scope => $args->{scope}) if defined $args->{scope};
$authorize_url->query->append(state => $args->{state}) if defined $args->{state};
$authorize_url->query->append(scope => $args->{scope}) if defined $args->{scope};
$authorize_url->query->append(state => $args->{state}) if defined $args->{state};
$authorize_url->query($args->{authorize_query}) if exists $args->{authorize_query};
$authorize_url;
}
Expand Down Expand Up @@ -219,7 +219,11 @@ sub _warmup_openid_provider_p {
my ($self, $app, $provider) = @_;

return $self->_ua->get_p($provider->{well_known_url})->then(sub {
my $tx = shift;
my $tx = shift;
if (my $err = $tx->error) {
die $err->{message};
}

my $res = $tx->result->json;
$provider->{authorize_url} = $res->{authorization_endpoint};
$provider->{end_session_url} = $res->{end_session_endpoint};
Expand All @@ -236,6 +240,8 @@ sub _warmup_openid_provider_p {
})->catch(sub {
my $err = shift;
$app->log->error("[OAuth2] Failed to warm up $provider->{well_known_url}: $err");
my $cb = $provider->{warmup_error_callback};
$cb->($provider, $err) if $cb and ref($cb) eq 'CODE';
});
}

Expand Down Expand Up @@ -526,13 +532,17 @@ Here is an example to add adddition information like "key" and "secret":

For L<OpenID Connect|https://openid.net/connect/>, C<authorize_url> and C<token_url> are configured from the
C<well_known_url> so these are replaced by the C<well_known_url> key.
To be able to handle errors during the fetch of the openid configuration via the well known URL you can
specify a subroutine reference as a callback with the key C<warmup_error_callback>. It will get a reference
to the provider hash and the error message as parameters.

$app->plugin(OAuth2 => {
providers => {
azure_ad => {
key => 'APP_ID',
secret => 'SECRET_KEY',
well_known_url => 'https://login.microsoftonline.com/tenant-id/v2.0/.well-known/openid-configuration',
key => 'APP_ID',
secret => 'SECRET_KEY',
well_known_url => 'https://login.microsoftonline.com/tenant-id/v2.0/.well-known/openid-configuration',
warmup_error_callback => sub { my($provider, $error) = @_; warn $error; }
},
},
});
Expand Down
10 changes: 8 additions & 2 deletions lib/Mojolicious/Plugin/OAuth2/Mock.pm
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,14 @@ sub _action_token_endpoint {
sub _action_well_known {
my ($self, $c) = @_;
my $provider = $self->provider;
my $req_url = $c->req->url->to_abs;
my $to_abs = sub { $req_url->path(Mojo::URL->new(shift)->path)->to_abs };

if ($provider->{key} eq 'invalid') {
$c->render(text => 'FAIL INVALID', status => 400);
return;
}

my $req_url = $c->req->url->to_abs;
my $to_abs = sub { $req_url->path(Mojo::URL->new(shift)->path)->to_abs };

$c->render(
template => 'oauth2/mock/configuration',
Expand Down
26 changes: 26 additions & 0 deletions t/oidc-error.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
use MIME::Base64 qw(encode_base64url);
use Mojo::JSON qw(decode_json encode_json);
use Mojo::URL;
use Mojolicious::Plugin::OAuth2;

plan skip_all => "Mojo::JWT, Crypt::OpenSSL::RSA and Crypt::OpenSSL::Bignum required for openid tests"
unless Mojolicious::Plugin::OAuth2::MOJO_JWT;

use Mojolicious::Lite;

my $error = '';

plugin OAuth2 => {
mocked => {
key => 'invalid',
well_known_url => '/mocked/oauth2/.well-known/configuration',
warmup_error_callback => sub { $error = $_[1] },
}
};

like($error, qr/^Bad Request/, 'invalid key triggers callback');

done_testing;