Manage OIDC Implicit Flow (#184)
This commit is contained in:
parent
33bc52b619
commit
89e3678bdf
@ -47,7 +47,8 @@ sub issuerForUnAuthUser {
|
|||||||
'debug' );
|
'debug' );
|
||||||
|
|
||||||
# Save parameters
|
# Save parameters
|
||||||
foreach my $param (qw/response_type scope client_id state redirect_uri/)
|
foreach
|
||||||
|
my $param (qw/response_type scope client_id state redirect_uri nonce/)
|
||||||
{
|
{
|
||||||
$self->setHiddenFormValue( $param,
|
$self->setHiddenFormValue( $param,
|
||||||
$self->getHiddenFormValue($param) || $self->param($param) );
|
$self->getHiddenFormValue($param) || $self->param($param) );
|
||||||
@ -271,6 +272,7 @@ sub issuerForAuthUser {
|
|||||||
my $authorize_uri = $self->{issuerDBOpenIDConnectAuthorizeURI};
|
my $authorize_uri = $self->{issuerDBOpenIDConnectAuthorizeURI};
|
||||||
my $token_uri = $self->{issuerDBOpenIDConnectTokenURI};
|
my $token_uri = $self->{issuerDBOpenIDConnectTokenURI};
|
||||||
my $userinfo_uri = $self->{issuerDBOpenIDConnectUserInfoURI};
|
my $userinfo_uri = $self->{issuerDBOpenIDConnectUserInfoURI};
|
||||||
|
my $issuer = $self->{oidcServiceMetaDataIssuer};
|
||||||
|
|
||||||
# Session ID
|
# Session ID
|
||||||
my $session_id = $self->{sessionInfo}->{_session_id} || $self->{id};
|
my $session_id = $self->{sessionInfo}->{_session_id} || $self->{id};
|
||||||
@ -321,6 +323,8 @@ sub issuerForAuthUser {
|
|||||||
"OIDC $flow flow requested (response type: $response_type)",
|
"OIDC $flow flow requested (response type: $response_type)",
|
||||||
'debug' );
|
'debug' );
|
||||||
|
|
||||||
|
# TODO Send error responses depending on the flow
|
||||||
|
|
||||||
# TODO check all required parameters
|
# TODO check all required parameters
|
||||||
if ( $flow eq "implicit" and not defined $oidc_request->{'nonce'} ) {
|
if ( $flow eq "implicit" and not defined $oidc_request->{'nonce'} ) {
|
||||||
$self->lmLog( "Nonce is required for implicit flow", 'error' );
|
$self->lmLog( "Nonce is required for implicit flow", 'error' );
|
||||||
@ -336,24 +340,20 @@ sub issuerForAuthUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Check client_id
|
# Check client_id
|
||||||
$self->lmLog( "Request from client id " . $oidc_request->{'client_id'},
|
my $client_id = $oidc_request->{'client_id'};
|
||||||
'debug' );
|
$self->lmLog( "Request from client id $client_id", 'debug' );
|
||||||
|
|
||||||
# Verify that client_id is registered in configuration
|
# Verify that client_id is registered in configuration
|
||||||
my $rp = $self->getRP( $oidc_request->{'client_id'} );
|
my $rp = $self->getRP($client_id);
|
||||||
|
|
||||||
unless ($rp) {
|
unless ($rp) {
|
||||||
$self->lmLog(
|
$self->lmLog(
|
||||||
"No registered Relying Party found with client_id "
|
"No registered Relying Party found with client_id $client_id",
|
||||||
. $oidc_request->{'client_id'},
|
'error' );
|
||||||
'error'
|
|
||||||
);
|
|
||||||
return PE_ERROR;
|
return PE_ERROR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->lmLog(
|
$self->lmLog( "Client id $client_id match RP $rp", 'debug' );
|
||||||
"Client id " . $oidc_request->{'client_id'} . " match RP $rp",
|
|
||||||
'debug' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Obtain consent
|
# Obtain consent
|
||||||
@ -485,11 +485,83 @@ sub issuerForAuthUser {
|
|||||||
# Implicit Flow
|
# Implicit Flow
|
||||||
if ( $flow eq "implicit" ) {
|
if ( $flow eq "implicit" ) {
|
||||||
|
|
||||||
#TODO
|
my $access_token;
|
||||||
|
|
||||||
|
if ( $response_type =~ /\btoken\b/ ) {
|
||||||
|
|
||||||
|
# Generate access_token
|
||||||
|
my $accessTokenSession = $self->getOpenIDConnectSession;
|
||||||
|
|
||||||
|
unless ($accessTokenSession) {
|
||||||
|
$self->lmLog(
|
||||||
|
"Unable to create OIDC session for access_token",
|
||||||
|
"error" );
|
||||||
return PE_ERROR;
|
return PE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Store data in access token
|
||||||
|
$accessTokenSession->update(
|
||||||
|
{
|
||||||
|
scope => $oidc_request->{'scope'},
|
||||||
|
rp => $rp,
|
||||||
|
user_session_id => $session_id,
|
||||||
|
_utime => time,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$access_token = $accessTokenSession->id;
|
||||||
|
|
||||||
|
$self->lmLog( "Generated access token: $access_token",
|
||||||
|
'debug' );
|
||||||
|
}
|
||||||
|
|
||||||
|
# ID token payload
|
||||||
|
my $id_token_exp = $self->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsIDTokenExpiration};
|
||||||
|
|
||||||
|
my $id_token_acr =
|
||||||
|
"loa-" . $self->{sessionInfo}->{authenticationLevel};
|
||||||
|
|
||||||
|
my $user_id_attribute = $self->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsUserIDAttr} || $self->{whatToTrace};
|
||||||
|
my $user_id = $self->{sessionInfo}->{$user_id_attribute};
|
||||||
|
|
||||||
|
my $id_token_payload_hash = {
|
||||||
|
iss => $issuer, # Issuer Identifier
|
||||||
|
sub => $user_id, # Subject Identifier
|
||||||
|
aud => [$client_id], # Audience
|
||||||
|
exp => $id_token_exp, # expiration
|
||||||
|
iat => time, # Issued time
|
||||||
|
auth_time =>
|
||||||
|
$self->{sessionInfo}->{_lastAuthnUTime}, # Authentication time
|
||||||
|
acr => $id_token_acr, # Authentication Context Class Reference
|
||||||
|
azp => $client_id, # Authorized party
|
||||||
|
# TODO amr
|
||||||
|
nonce => $oidc_request->{'nonce'} # Nonce
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create ID Token
|
||||||
|
my $id_token = $self->createIDToken( $id_token_payload_hash, $rp );
|
||||||
|
|
||||||
|
$self->lmLog( "Generated id token: $id_token", 'debug' );
|
||||||
|
|
||||||
|
# Send token response
|
||||||
|
my $expires_in = $self->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsAccessTokenExpiration};
|
||||||
|
|
||||||
|
# Build Response
|
||||||
|
my $response_url =
|
||||||
|
$self->buildImplicitAuthnResponse(
|
||||||
|
$oidc_request->{'redirect_uri'},
|
||||||
|
$access_token, $id_token, $expires_in,
|
||||||
|
$oidc_request->{'state'} );
|
||||||
|
|
||||||
|
$self->lmLog( "Redirect user to $response_url", 'debug' );
|
||||||
|
$self->{'urldc'} = $response_url;
|
||||||
|
|
||||||
|
$self->_sub('autoRedirect');
|
||||||
|
}
|
||||||
|
|
||||||
# Hybrid Flow
|
# Hybrid Flow
|
||||||
if ( $flow eq "hybrid" ) {
|
if ( $flow eq "hybrid" ) {
|
||||||
|
|
||||||
|
@ -273,6 +273,38 @@ sub buildAuthorizationCodeAuthnResponse {
|
|||||||
return $response_url;
|
return $response_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## @method String buildImplicitAuthnResponse(String redirect_uri, String access_token, String id_token, String expires_in, String state)
|
||||||
|
# Build Authentication Response URI for Implicit Flow
|
||||||
|
# @param redirect_uri Redirect URI
|
||||||
|
# @param access_token Access token
|
||||||
|
# @param id_token ID token
|
||||||
|
# @param expires_in Expiration of access token
|
||||||
|
# @param state State
|
||||||
|
# return String Authentication Response URI
|
||||||
|
sub buildImplicitAuthnResponse {
|
||||||
|
my ( $self, $redirect_uri, $access_token, $id_token, $expires_in, $state )
|
||||||
|
= splice @_;
|
||||||
|
|
||||||
|
my $response_url = $redirect_uri;
|
||||||
|
|
||||||
|
$response_url .= "#id_token=" . uri_escape($id_token);
|
||||||
|
|
||||||
|
if ($access_token) {
|
||||||
|
$response_url .= "&access_token=" . uri_escape($access_token);
|
||||||
|
$response_url .= "&token_type=bearer";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($expires_in) {
|
||||||
|
$response_url .= "&expires_in=" . uri_escape($expires_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($state) {
|
||||||
|
$response_url .= "&state=" . uri_escape($state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response_url;
|
||||||
|
}
|
||||||
|
|
||||||
## @method String getAuthorizationCodeAccessToken(String op, String code, String auth_method)
|
## @method String getAuthorizationCodeAccessToken(String op, String code, String auth_method)
|
||||||
# Get Token response with autorization code
|
# Get Token response with autorization code
|
||||||
# @param op OpenIP Provider configuration key
|
# @param op OpenIP Provider configuration key
|
||||||
@ -1006,6 +1038,10 @@ Build Authentication Request URI for Authorization Code Flow
|
|||||||
|
|
||||||
Build Authentication Response URI for Authorization Code Flow
|
Build Authentication Response URI for Authorization Code Flow
|
||||||
|
|
||||||
|
=head2 buildImplicitAuthnResponse
|
||||||
|
|
||||||
|
Build Authentication Response URI for Implicit Flow
|
||||||
|
|
||||||
=head2 getAuthorizationCodeAccessToken
|
=head2 getAuthorizationCodeAccessToken
|
||||||
|
|
||||||
Get Token response with autorization code
|
Get Token response with autorization code
|
||||||
|
Loading…
Reference in New Issue
Block a user