aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/OIDC/Lite/Client
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/OIDC/Lite/Client')
-rw-r--r--perllib/OIDC/Lite/Client/IDTokenResponseParser.pm72
-rw-r--r--perllib/OIDC/Lite/Client/WebServer/Azure.pm39
2 files changed, 111 insertions, 0 deletions
diff --git a/perllib/OIDC/Lite/Client/IDTokenResponseParser.pm b/perllib/OIDC/Lite/Client/IDTokenResponseParser.pm
new file mode 100644
index 000000000..41db1bbdb
--- /dev/null
+++ b/perllib/OIDC/Lite/Client/IDTokenResponseParser.pm
@@ -0,0 +1,72 @@
+package OIDC::Lite::Client::IDTokenResponseParser;
+
+use strict;
+use warnings;
+
+use Try::Tiny qw/try catch/;
+use OIDC::Lite::Model::IDToken;
+use OAuth::Lite2::Formatters;
+use OAuth::Lite2::Client::Error;
+
+=head1 NAME
+
+OIDC::Lite::Client::IDTokenResponseParser - parse id_token JWT into an
+L<OIDC::Lite::Model::IDToken> object.
+
+Acts the same as L<OIDC::Lite::Client::TokenResponseParser> but looks for an
+id_token in the HTTP response instead of access_token.
+
+=cut
+
+sub new {
+ bless {}, $_[0];
+}
+
+sub parse {
+ my ($self, $http_res) = @_;
+
+ my $formatter =
+ OAuth::Lite2::Formatters->get_formatter_by_type(
+ $http_res->content_type);
+
+ my $token;
+
+ if ($http_res->is_success) {
+
+ OAuth::Lite2::Client::Error::InvalidResponse->throw(
+ message => sprintf(q{Invalid response content-type: %s},
+ $http_res->content_type||'')
+ ) unless $formatter;
+
+ my $result = try {
+ return $formatter->parse($http_res->content);
+ } catch {
+ OAuth::Lite2::Client::Error::InvalidResponse->throw(
+ message => sprintf(q{Invalid response format: %s}, $_),
+ );
+ };
+
+ OAuth::Lite2::Client::Error::InvalidResponse->throw(
+ message => sprintf("Response doesn't include 'id_token'")
+ ) unless exists $result->{id_token};
+
+ $token = OIDC::Lite::Model::IDToken->load($result->{id_token});
+
+ } else {
+
+ my $errmsg = $http_res->content || $http_res->status_line;
+ if ($formatter && $http_res->content) {
+ try {
+ my $result = $formatter->parse($http_res->content);
+ $errmsg = $result->{error}
+ if exists $result->{error};
+ } catch {
+ return OAuth::Lite2::Client::Error::InvalidResponse->throw;
+ };
+ }
+ OAuth::Lite2::Client::Error::InvalidResponse->throw( message => $errmsg );
+ }
+ return $token;
+}
+
+1;
diff --git a/perllib/OIDC/Lite/Client/WebServer/Azure.pm b/perllib/OIDC/Lite/Client/WebServer/Azure.pm
new file mode 100644
index 000000000..b19dce90e
--- /dev/null
+++ b/perllib/OIDC/Lite/Client/WebServer/Azure.pm
@@ -0,0 +1,39 @@
+package OIDC::Lite::Client::WebServer::Azure;
+
+use strict;
+use warnings;
+use parent 'OIDC::Lite::Client::WebServer';
+
+use OIDC::Lite::Client::IDTokenResponseParser;
+
+=head1 NAME
+
+OIDC::Lite::Client::WebServer::Azure - extension to auth against Azure AD B2C
+
+OIDC::Lite doesn't appear to support the authorisation code flow to get an
+ID token - only an access token. Azure returns all its claims in the id_token
+and doesn't support a UserInfo endpoint, so this extension adds support for
+parsing the id_token when calling get_access_token.
+
+=cut
+
+=head2 new
+
+Overrides response_parser so that get_access_token returns a
+L<OIDC::Lite::Model::IDToken> object.
+
+NB this does not perform any verification of the id_token. It's assumed to be
+safe as it's come directly from the OpenID IdP and not an untrusted user's
+browser.
+
+=cut
+
+sub new {
+ my $self = shift->next::method(@_);
+
+ $self->{response_parser} = OIDC::Lite::Client::IDTokenResponseParser->new;
+
+ return $self;
+}
+
+1;