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
|
||||
$self->lmLog( "Build OpenIDConnect AuthN Request", 'debug' );
|
||||
|
||||
# TODO Save state
|
||||
my $state = "dummy";
|
||||
# Save state
|
||||
my $state = $self->storeState( qw/urldc checkLogins/ );
|
||||
|
||||
my $stateSession = $self->storeState();
|
||||
|
||||
# TODO Use AuthChoiceParam in redirect URL
|
||||
|
||||
# Authorization Code Flow
|
||||
$self->{urldc} = $self->buildAuthorizationCodeAuthnRequest($state);
|
||||
|
@ -72,7 +76,16 @@ sub extractFormInfo {
|
|||
my $state = $self->param("state");
|
||||
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
|
||||
my $content = $self->getAuthorizationCodeAccessToken($code);
|
||||
|
|
|
@ -116,6 +116,111 @@ sub decodeJSON {
|
|||
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;
|
||||
|
||||
__END__
|
||||
|
@ -153,6 +258,18 @@ Get Token response with autorization code
|
|||
|
||||
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
|
||||
|
||||
L<Lemonldap::NG::Portal::AuthOpenIDConnect>, L<Lemonldap::NG::Portal::UserDBOpenIDConnect>
|
||||
|
|
Loading…
Reference in New Issue
Block a user