From 968f0e065a047542c5ab94ca0ec29a327fb86a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Oudot?= Date: Mon, 2 Feb 2015 09:44:33 +0000 Subject: [PATCH] Check authentication on token endpoint (#184) --- .../NG/Portal/IssuerDBOpenIDConnect.pm | 57 +++++++++++++++---- .../lib/Lemonldap/NG/Portal/_OpenIDConnect.pm | 26 ++++++++- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/IssuerDBOpenIDConnect.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/IssuerDBOpenIDConnect.pm index 63825f680..acfb7e401 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/IssuerDBOpenIDConnect.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/IssuerDBOpenIDConnect.pm @@ -64,7 +64,42 @@ sub issuerForUnAuthUser { $self->lmLog( "URL $url detected as an OpenID Connect TOKEN URL", 'debug' ); - # TODO check authorization header or other authentication scheme + # Check authentication + my ( $client_id, $client_secret ) = + $self->getEndPointAuthenticationCredentials(); + + unless ( $client_id && $client_secret ) { + $self->lmLog( +"No authentication provided to get token, or authentication type not supported", + "error" + ); + $self->returnJSONError("unauthorized_client"); + $self->quit; + } + + # Verify that client_id is registered in configuration + my $rp = $self->getRP($client_id); + + unless ($rp) { + $self->lmLog( + "No registered Relaying Party found with client_id $client_id", + 'error' + ); + $self->returnJSONError("unauthorized_client"); + $self->quit; + } + else { + $self->lmLog( "Client id $client_id match RP $rp", 'debug' ); + } + + # Check client_secret + unless ( $client_secret eq $self->{oidcRPMetaDataOptions}->{$rp} + ->{oidcRPMetaDataOptionsClientSecret} ) + { + $self->lmLog( "Wrong credentials", "error" ); + $self->returnJSONError("access_denied"); + $self->quit; + } # Get code session my $code = $self->param('code'); @@ -130,15 +165,15 @@ sub issuerForUnAuthUser { # Create id_token my $id_token_payload_hash = { - iss => $issuer, # Issuer Identifier - sub => $user_id, # Subject Identifier - aud => "dummy", # client_id TODO - exp => "3600", # expiration TODO - iat => time, # Issued time - auth_time => time # Authentication time TODO - # TODO acr - # TODO amr - # TODO azp + iss => $issuer, # Issuer Identifier + sub => $user_id, # Subject Identifier + aud => $client_id, # Audience + exp => "3600", # expiration TODO + iat => time, # Issued time + auth_time => time # Authentication time TODO + # TODO acr + # TODO amr + # TODO azp }; # JSON and base64 @@ -256,7 +291,7 @@ sub issuerForAuthUser { } else { $self->lmLog( - "Cient id " + "Client id " . $oidc_request->{'client_id'} . " match RP $rp", 'debug' diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_OpenIDConnect.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_OpenIDConnect.pm index b107ec335..643409001 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_OpenIDConnect.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_OpenIDConnect.pm @@ -721,7 +721,7 @@ sub returnJSONError { print encode_json( { "error" => "$error" } ); } -## @method coid returnJSON(String content); +## @method void returnJSON(String content); # Print JSON content # @param content Message # @return void @@ -731,6 +731,26 @@ sub returnJSON { print $self->header('application/json'); print encode_json($content); } +## @method array getEndPointAuthenticationCredentials() +# Get Client ID and Client Secret +# @return array (client_id, client_secret) +sub getEndPointAuthenticationCredentials { + my $self = shift; + my ( $client_id, $client_secret ); + + my $authorization = $ENV{HTTP_AUTHORIZATION}; + if ( $authorization =~ /^Basic (\w+)/i ) { + $self->lmLog( "Method client_secret_basic used", 'debug' ); + ( $client_id, $client_secret ) = split( /:/, decode_base64($1) ); + } + elsif ( $self->param('client_id') && $self->param('client_secret') ) { + $self->lmLog( "Method client_secret_post used", 'debug' ); + $client_id = $self->param('client_id'); + $client_secret = $self->param('client_secret'); + } + + return ( $client_id, $client_secret ); +} 1; @@ -821,6 +841,10 @@ Print JSON error Print JSON content +=head2 getEndPointAuthenticationCredentials + +Get Client ID and Client Secret + =head1 SEE ALSO L, L