Save/restore state in OpenID Connect RP (#183)
This commit is contained in:
parent
c64f69a852
commit
3cde211810
@ -50,8 +50,12 @@ sub extractFormInfo {
|
|||||||
# AuthN Request
|
# AuthN Request
|
||||||
$self->lmLog( "Build OpenIDConnect AuthN Request", 'debug' );
|
$self->lmLog( "Build OpenIDConnect AuthN Request", 'debug' );
|
||||||
|
|
||||||
# TODO Save state
|
# Save state
|
||||||
my $state = "dummy";
|
my $state = $self->storeState( qw/urldc checkLogins/ );
|
||||||
|
|
||||||
|
my $stateSession = $self->storeState();
|
||||||
|
|
||||||
|
# TODO Use AuthChoiceParam in redirect URL
|
||||||
|
|
||||||
# Authorization Code Flow
|
# Authorization Code Flow
|
||||||
$self->{urldc} = $self->buildAuthorizationCodeAuthnRequest($state);
|
$self->{urldc} = $self->buildAuthorizationCodeAuthnRequest($state);
|
||||||
@ -72,7 +76,16 @@ sub extractFormInfo {
|
|||||||
my $state = $self->param("state");
|
my $state = $self->param("state");
|
||||||
my $code = $self->param("code");
|
my $code = $self->param("code");
|
||||||
|
|
||||||
# TODO Restore state
|
# Restore state
|
||||||
|
if ($state) {
|
||||||
|
if ( $self->extractState($state) ) {
|
||||||
|
$self->lmLog( "State $state extracted", 'debug' );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$self->lmLog( "Unable to extract state $state", 'error' );
|
||||||
|
return PE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Get access_token and id_token
|
# Get access_token and id_token
|
||||||
my $content = $self->getAuthorizationCodeAccessToken($code);
|
my $content = $self->getAuthorizationCodeAccessToken($code);
|
||||||
|
@ -116,6 +116,111 @@ sub decodeJSON {
|
|||||||
return $json_hash;
|
return $json_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## @method hashref getOpenIDConnectSession(string id)
|
||||||
|
# Try to recover the OpenID Connect session corresponding to id and return session
|
||||||
|
# If id is set to undef, return a new session
|
||||||
|
# @param id session reference
|
||||||
|
# @return Lemonldap::NG::Common::Session object
|
||||||
|
sub getOpenIDConnectSession {
|
||||||
|
my ( $self, $id ) = splice @_;
|
||||||
|
|
||||||
|
my $oidcSession = Lemonldap::NG::Common::Session->new(
|
||||||
|
{
|
||||||
|
storageModule => $self->{globalStorage},
|
||||||
|
storageModuleOptions => $self->{globalStorageOptions},
|
||||||
|
cacheModule => $self->{localSessionStorage},
|
||||||
|
cacheModuleOptions => $self->{localSessionStorageOptions},
|
||||||
|
id => $id,
|
||||||
|
kind => "OpenIDConnect",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $oidcSession->error ) {
|
||||||
|
if ($id) {
|
||||||
|
$self->_sub( 'userInfo',
|
||||||
|
"OpenIDConnect session $id isn't yet available" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$self->lmLog( "Unable to create new OpenIDConnect session",
|
||||||
|
'error' );
|
||||||
|
$self->lmLog( $oidcSession->error, 'error' );
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $oidcSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string storeState(array data)
|
||||||
|
# Store information in state database and return
|
||||||
|
# corresponding session_id
|
||||||
|
# @param data Array of information to store
|
||||||
|
# @return State Session ID
|
||||||
|
sub storeState {
|
||||||
|
my ( $self, @data ) = splice @_;
|
||||||
|
|
||||||
|
# check if there are data to store
|
||||||
|
my $infos;
|
||||||
|
foreach (@data) {
|
||||||
|
$infos->{$_} = $self->{$_} if $self->{$_};
|
||||||
|
}
|
||||||
|
return unless ($infos);
|
||||||
|
|
||||||
|
# Create state session
|
||||||
|
my $stateSession = $self->getOpenIDConnectSession();
|
||||||
|
|
||||||
|
return unless $stateSession;
|
||||||
|
|
||||||
|
# Session type
|
||||||
|
$infos->{_type} = "state";
|
||||||
|
|
||||||
|
# Set _utime for session autoremove
|
||||||
|
# Use default session timeout and relayState session timeout to compute it
|
||||||
|
my $time = time();
|
||||||
|
my $timeout = $self->{timeout};
|
||||||
|
my $stateTimeout = $self->{OIDCRPStateTimeout} || $timeout;
|
||||||
|
|
||||||
|
$infos->{_utime} = $time + ( $stateTimeout - $timeout );
|
||||||
|
|
||||||
|
# Store infos in state session
|
||||||
|
$stateSession->update($infos);
|
||||||
|
|
||||||
|
# Return session ID
|
||||||
|
return $stateSession->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method boolean extractState(string state)
|
||||||
|
# Extract state information into $self
|
||||||
|
# @param state state value
|
||||||
|
# @return result
|
||||||
|
sub extractState {
|
||||||
|
my ( $self, $state ) = splice @_;
|
||||||
|
|
||||||
|
return 0 unless $state;
|
||||||
|
|
||||||
|
# Open state session
|
||||||
|
my $stateSession = $self->getOpenIDConnectSession($state);
|
||||||
|
|
||||||
|
return 0 unless $stateSession;
|
||||||
|
|
||||||
|
# Push values in $self
|
||||||
|
foreach ( keys %{ $stateSession->data } ) {
|
||||||
|
next if $_ =~ /(type|_session_id|_utime)/;
|
||||||
|
$self->{$_} = $stateSession->data->{$_};
|
||||||
|
}
|
||||||
|
|
||||||
|
# Delete state session
|
||||||
|
if ( $stateSession->remove ) {
|
||||||
|
$self->lmLog( "State $state was deleted", 'debug' );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$self->lmLog( "Unable to delete state $state", 'error' );
|
||||||
|
$self->lmLog( $stateSession->error, 'error' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
__END__
|
__END__
|
||||||
@ -153,6 +258,18 @@ Get Token response with autorization code
|
|||||||
|
|
||||||
Convert JSON to HashRef
|
Convert JSON to HashRef
|
||||||
|
|
||||||
|
=head2 getOpenIDConnectSession
|
||||||
|
|
||||||
|
Try to recover the OpenID Connect session corresponding to id and return session
|
||||||
|
|
||||||
|
=head2 storeState
|
||||||
|
|
||||||
|
Store information in state database and return
|
||||||
|
|
||||||
|
=head2 extractState
|
||||||
|
|
||||||
|
Extract state information into $self
|
||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
L<Lemonldap::NG::Portal::AuthOpenIDConnect>, L<Lemonldap::NG::Portal::UserDBOpenIDConnect>
|
L<Lemonldap::NG::Portal::AuthOpenIDConnect>, L<Lemonldap::NG::Portal::UserDBOpenIDConnect>
|
||||||
|
Loading…
Reference in New Issue
Block a user