diff options
Diffstat (limited to 'perllib/OIDC')
-rw-r--r-- | perllib/OIDC/Lite/Client/IDTokenResponseParser.pm | 72 | ||||
-rw-r--r-- | perllib/OIDC/Lite/Client/WebServer/Azure.pm | 39 |
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; |