Manager UserInfo signature (JWT response) (#184)
This commit is contained in:
parent
e84963ac32
commit
9520bef489
|
@ -339,7 +339,7 @@ sub cstruct {
|
||||||
},
|
},
|
||||||
oidcRPMetaDataOptions => {
|
oidcRPMetaDataOptions => {
|
||||||
_nodes => [
|
_nodes => [
|
||||||
qw(oidcRPMetaDataOptionsAuthentication oidcRPMetaDataOptionsDisplay oidcRPMetaDataOptionsUserIDAttr oidcRPMetaDataOptionsIDTokenSignAlg oidcRPMetaDataOptionsIDTokenExpiration oidcRPMetaDataOptionsAccessTokenExpiration oidcRPMetaDataOptionsRedirectUris)
|
qw(oidcRPMetaDataOptionsAuthentication oidcRPMetaDataOptionsDisplay oidcRPMetaDataOptionsUserIDAttr oidcRPMetaDataOptionsIDTokenSignAlg oidcRPMetaDataOptionsIDTokenExpiration oidcRPMetaDataOptionsAccessTokenExpiration oidcRPMetaDataOptionsRedirectUris oidcRPMetaDataOptionsUserInfoSignAlg)
|
||||||
],
|
],
|
||||||
oidcRPMetaDataOptionsAuthentication => {
|
oidcRPMetaDataOptionsAuthentication => {
|
||||||
_nodes => [
|
_nodes => [
|
||||||
|
@ -369,6 +369,8 @@ sub cstruct {
|
||||||
"int:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsAccessTokenExpiration",
|
"int:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsAccessTokenExpiration",
|
||||||
oidcRPMetaDataOptionsRedirectUris =>
|
oidcRPMetaDataOptionsRedirectUris =>
|
||||||
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsRedirectUris",
|
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsRedirectUris",
|
||||||
|
oidcRPMetaDataOptionsUserInfoSignAlg =>
|
||||||
|
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsUserInfoSignAlg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -303,45 +303,46 @@ sub en {
|
||||||
oidcRPMetaDataOptionsDisplayName => 'Display name',
|
oidcRPMetaDataOptionsDisplayName => 'Display name',
|
||||||
oidcRPMetaDataOptionsIcon => 'Logo',
|
oidcRPMetaDataOptionsIcon => 'Logo',
|
||||||
oidcRPMetaDataOptionsIDTokenExpiration => 'ID Token expiration',
|
oidcRPMetaDataOptionsIDTokenExpiration => 'ID Token expiration',
|
||||||
oidcRPMetaDataOptionsIDTokenSignAlg => 'ID Token signature algorithm',
|
oidcRPMetaDataOptionsIDTokenSignAlg => 'ID Token signature algorithm',
|
||||||
oidcRPMetaDataOptionsRedirectUris => 'Redirection addresses',
|
oidcRPMetaDataOptionsRedirectUris => 'Redirection addresses',
|
||||||
oidcRPMetaDataOptionsUserIDAttr => 'User ID attribute',
|
oidcRPMetaDataOptionsUserIDAttr => 'User ID attribute',
|
||||||
oidcRPStateTimeout => 'State session timeout',
|
oidcRPMetaDataOptionsUserInfoSignAlg => 'UserInfo signature algorithm',
|
||||||
oidcServiceMetaData => 'OpenID Connect Service',
|
oidcRPStateTimeout => 'State session timeout',
|
||||||
oidcServiceMetaDataAuthnContext => 'Authentication context',
|
oidcServiceMetaData => 'OpenID Connect Service',
|
||||||
oidcServiceMetaDataAuthorizeURI => 'Autorization',
|
oidcServiceMetaDataAuthnContext => 'Authentication context',
|
||||||
oidcServiceMetaDataEndPoints => 'End points',
|
oidcServiceMetaDataAuthorizeURI => 'Autorization',
|
||||||
oidcServiceMetaDataEndSessionURI => 'End session',
|
oidcServiceMetaDataEndPoints => 'End points',
|
||||||
oidcServiceMetaDataIssuer => 'Issuer identifier',
|
oidcServiceMetaDataEndSessionURI => 'End session',
|
||||||
oidcServiceMetaDataJWKSURI => 'JWKS',
|
oidcServiceMetaDataIssuer => 'Issuer identifier',
|
||||||
oidcServiceMetaDataRegistrationURI => 'Registration',
|
oidcServiceMetaDataJWKSURI => 'JWKS',
|
||||||
oidcServiceMetaDataSecurity => 'Security',
|
oidcServiceMetaDataRegistrationURI => 'Registration',
|
||||||
oidcServiceMetaDataTokenURI => 'Token',
|
oidcServiceMetaDataSecurity => 'Security',
|
||||||
oidcServiceMetaDataUserInfoURI => 'User Info',
|
oidcServiceMetaDataTokenURI => 'Token',
|
||||||
oidcServicePrivateKeySig => 'Signing private key',
|
oidcServiceMetaDataUserInfoURI => 'User Info',
|
||||||
oidcServicePublicKeySig => 'Signing public key',
|
oidcServicePrivateKeySig => 'Signing private key',
|
||||||
openIdAttr => 'OpenID login',
|
oidcServicePublicKeySig => 'Signing public key',
|
||||||
openIdAuthnLevel => 'Authentication level',
|
openIdAttr => 'OpenID login',
|
||||||
openIdExportedVars => 'Exported variables',
|
openIdAuthnLevel => 'Authentication level',
|
||||||
openIdIDPList => 'Authorizated domains',
|
openIdExportedVars => 'Exported variables',
|
||||||
openIdIssuerSecret => 'Secret token',
|
openIdIDPList => 'Authorizated domains',
|
||||||
openIdParams => 'OpenID parameters',
|
openIdIssuerSecret => 'Secret token',
|
||||||
openIdSecret => 'Secret token',
|
openIdParams => 'OpenID parameters',
|
||||||
openIdSreg => 'SREG mapping',
|
openIdSecret => 'Secret token',
|
||||||
openIdSreg_fullname => 'Full name',
|
openIdSreg => 'SREG mapping',
|
||||||
openIdSreg_nickname => 'Nick name',
|
openIdSreg_fullname => 'Full name',
|
||||||
openIdSreg_language => 'Language',
|
openIdSreg_nickname => 'Nick name',
|
||||||
openIdSreg_postcode => 'Postal code',
|
openIdSreg_language => 'Language',
|
||||||
openIdSreg_timezone => 'Timezone',
|
openIdSreg_postcode => 'Postal code',
|
||||||
openIdSreg_country => 'Country',
|
openIdSreg_timezone => 'Timezone',
|
||||||
openIdSreg_gender => 'Gender',
|
openIdSreg_country => 'Country',
|
||||||
openIdSreg_email => 'Email',
|
openIdSreg_gender => 'Gender',
|
||||||
openIdSreg_dob => 'Date of birth',
|
openIdSreg_email => 'Email',
|
||||||
openIdSPList => 'Authorizated domains',
|
openIdSreg_dob => 'Date of birth',
|
||||||
passwordDB => 'Password module',
|
openIdSPList => 'Authorizated domains',
|
||||||
passwordManagement => 'Password management',
|
passwordDB => 'Password module',
|
||||||
persistentSessions => 'Persistent sessions',
|
passwordManagement => 'Password management',
|
||||||
persistentStorage => 'Apache::Session module',
|
persistentSessions => 'Persistent sessions',
|
||||||
|
persistentStorage => 'Apache::Session module',
|
||||||
persistentStorageOptions => 'Apache::Session module parameters',
|
persistentStorageOptions => 'Apache::Session module parameters',
|
||||||
port => 'Port',
|
port => 'Port',
|
||||||
portal => 'URL',
|
portal => 'URL',
|
||||||
|
@ -879,8 +880,10 @@ sub fr {
|
||||||
"Expiration des jetons d'identité",
|
"Expiration des jetons d'identité",
|
||||||
oidcRPMetaDataOptionsIDTokenSignAlg =>
|
oidcRPMetaDataOptionsIDTokenSignAlg =>
|
||||||
"Algorithme de signature des jetons d'identité",
|
"Algorithme de signature des jetons d'identité",
|
||||||
oidcRPMetaDataOptionsRedirectUris => 'Adresses de redirection',
|
oidcRPMetaDataOptionsRedirectUris => 'Adresses de redirection',
|
||||||
oidcRPMetaDataOptionsUserIDAttr => "Attribut de l'identifiant",
|
oidcRPMetaDataOptionsUserIDAttr => "Attribut de l'identifiant",
|
||||||
|
oidcRPMetaDataOptionsUserInfoSignAlg =>
|
||||||
|
"Algorithme de signature des informations utilisateur",
|
||||||
oidcRPStateTimeout => 'Durée d\'une session state',
|
oidcRPStateTimeout => 'Durée d\'une session state',
|
||||||
oidcServiceMetaData => "Service OpenID Connect",
|
oidcServiceMetaData => "Service OpenID Connect",
|
||||||
oidcServiceMetaDataAuthnContext => "Contextes d'authentifiation",
|
oidcServiceMetaDataAuthnContext => "Contextes d'authentifiation",
|
||||||
|
|
|
@ -50,6 +50,9 @@ $configuration->{id_token_signing_alg_values_supported} =
|
||||||
|
|
||||||
# $configuration->{id_token_encryption_alg_values_supported}
|
# $configuration->{id_token_encryption_alg_values_supported}
|
||||||
# $configuration->{id_token_encryption_enc_values_supported}
|
# $configuration->{id_token_encryption_enc_values_supported}
|
||||||
|
$configuration->{userinfo_signing_alg_values_supported} =
|
||||||
|
[qw/none HS256 HS384 HS512 RS256 RS384 RS512/];
|
||||||
|
|
||||||
# $configuration->{userinfo_encryption_alg_values_supported}
|
# $configuration->{userinfo_encryption_alg_values_supported}
|
||||||
# $configuration->{userinfo_encryption_enc_values_supported}
|
# $configuration->{userinfo_encryption_enc_values_supported}
|
||||||
# $configuration->{request_object_signing_alg_values_supported}
|
# $configuration->{request_object_signing_alg_values_supported}
|
||||||
|
|
|
@ -327,7 +327,19 @@ sub issuerForUnAuthUser {
|
||||||
my $userinfo_response =
|
my $userinfo_response =
|
||||||
$self->buildUserInfoResponse( $scope, $rp, $user_session_id );
|
$self->buildUserInfoResponse( $scope, $rp, $user_session_id );
|
||||||
|
|
||||||
$self->returnJSON($userinfo_response);
|
my $userinfo_sign_alg = $self->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsUserInfoSignAlg};
|
||||||
|
|
||||||
|
unless ($userinfo_sign_alg) {
|
||||||
|
$self->returnJSON($userinfo_response);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my $userinfo_jwt =
|
||||||
|
$self->createJWT( $userinfo_response, $userinfo_sign_alg, $rp );
|
||||||
|
print $self->header('application/jwt');
|
||||||
|
print $userinfo_jwt;
|
||||||
|
$self->lmLog( "Return UserInfo as JWT: $userinfo_jwt", 'debug' );
|
||||||
|
}
|
||||||
|
|
||||||
$self->lmLog( "UserInfo response sent", 'debug' );
|
$self->lmLog( "UserInfo response sent", 'debug' );
|
||||||
|
|
||||||
|
|
|
@ -1189,30 +1189,25 @@ sub buildUserInfoResponse {
|
||||||
return $userinfo_response;
|
return $userinfo_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
## @method String createIDToken(hashref payload, String rp)
|
## @method String createJWT(hashref payload, String alg, String rp)
|
||||||
# Return ID Token
|
# Return JWT
|
||||||
# @param payload ID Token content
|
# @param payload JWT content
|
||||||
|
# @param alg Signature algorithm
|
||||||
# @param rp Internal Relying Party identifier
|
# @param rp Internal Relying Party identifier
|
||||||
# @return String id_token ID Token as JWT
|
# @return String jwt JWT
|
||||||
sub createIDToken {
|
sub createJWT {
|
||||||
my ( $self, $payload, $rp ) = splice @_;
|
my ( $self, $payload, $alg, $rp ) = splice @_;
|
||||||
|
|
||||||
# Get signature algorithm
|
|
||||||
my $alg = $self->{oidcRPMetaDataOptions}->{$rp}
|
|
||||||
->{oidcRPMetaDataOptionsIDTokenSignAlg};
|
|
||||||
$self->lmLog( "JWT signature algorithm: $alg", 'debug' );
|
|
||||||
|
|
||||||
# Payload encoding
|
# Payload encoding
|
||||||
my $id_token_payload = encode_base64( encode_json($payload), "" );
|
my $jwt_payload = encode_base64( encode_json($payload), "" );
|
||||||
|
|
||||||
# ID Token header
|
# JWT header
|
||||||
my $id_token_header_hash = { typ => "JWT", alg => $alg };
|
my $jwt_header_hash = { typ => "JWT", alg => $alg };
|
||||||
my $id_token_header =
|
my $jwt_header = encode_base64( encode_json($jwt_header_hash), "" );
|
||||||
encode_base64( encode_json($id_token_header_hash), "" );
|
|
||||||
|
|
||||||
if ( $alg eq "none" ) {
|
if ( $alg eq "none" ) {
|
||||||
|
|
||||||
return $id_token_header . "." . $id_token_payload;
|
return $jwt_header . "." . $jwt_payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $alg eq "HS256" or $alg eq "HS384" or $alg eq "HS512" ) {
|
if ( $alg eq "HS256" or $alg eq "HS384" or $alg eq "HS512" ) {
|
||||||
|
@ -1225,24 +1220,21 @@ sub createIDToken {
|
||||||
my $digest;
|
my $digest;
|
||||||
|
|
||||||
if ( $alg eq "HS256" ) {
|
if ( $alg eq "HS256" ) {
|
||||||
$digest =
|
$digest = hmac_sha256_base64( $jwt_header . "." . $jwt_payload,
|
||||||
hmac_sha256_base64( $id_token_header . "." . $id_token_payload,
|
|
||||||
$client_secret );
|
$client_secret );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $alg eq "HS384" ) {
|
if ( $alg eq "HS384" ) {
|
||||||
$digest =
|
$digest = hmac_sha384_base64( $jwt_header . "." . $jwt_payload,
|
||||||
hmac_sha384_base64( $id_token_header . "." . $id_token_payload,
|
|
||||||
$client_secret );
|
$client_secret );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $alg eq "HS512" ) {
|
if ( $alg eq "HS512" ) {
|
||||||
$digest =
|
$digest = hmac_sha512_base64( $jwt_header . "." . $jwt_payload,
|
||||||
hmac_sha512_base64( $id_token_header . "." . $id_token_payload,
|
|
||||||
$client_secret );
|
$client_secret );
|
||||||
}
|
}
|
||||||
|
|
||||||
return $id_token_header . "." . $id_token_payload . "." . $digest;
|
return $jwt_header . "." . $jwt_payload . "." . $digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $alg eq "RS256" or $alg eq "RS384" or $alg eq "RS512" ) {
|
if ( $alg eq "RS256" or $alg eq "RS384" or $alg eq "RS512" ) {
|
||||||
|
@ -1264,16 +1256,32 @@ sub createIDToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $digest = encode_base64url(
|
my $digest = encode_base64url(
|
||||||
$rsa_priv->sign( $id_token_header . "." . $id_token_payload ) );
|
$rsa_priv->sign( $jwt_header . "." . $jwt_payload ) );
|
||||||
|
|
||||||
return $id_token_header . "." . $id_token_payload . "." . $digest;
|
return $jwt_header . "." . $jwt_payload . "." . $digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->lmLog( "Algorithm $alg not supported to sign ID Token", 'debug' );
|
$self->lmLog( "Algorithm $alg not supported to sign JWT", 'debug' );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## @method String createIDToken(hashref payload, String rp)
|
||||||
|
# Return ID Token
|
||||||
|
# @param payload ID Token content
|
||||||
|
# @param rp Internal Relying Party identifier
|
||||||
|
# @return String id_token ID Token as JWT
|
||||||
|
sub createIDToken {
|
||||||
|
my ( $self, $payload, $rp ) = splice @_;
|
||||||
|
|
||||||
|
# Get signature algorithm
|
||||||
|
my $alg = $self->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsIDTokenSignAlg};
|
||||||
|
$self->lmLog( "ID Token signature algorithm: $alg", 'debug' );
|
||||||
|
|
||||||
|
return $self->createJWT( $payload, $alg, $rp );
|
||||||
|
}
|
||||||
|
|
||||||
## @method String getFlowType(String response_type)
|
## @method String getFlowType(String response_type)
|
||||||
# Return flow type
|
# Return flow type
|
||||||
# @param response_type Response type
|
# @param response_type Response type
|
||||||
|
@ -1522,6 +1530,10 @@ Return list of attributes authorized for a claim
|
||||||
|
|
||||||
Return Hash of UserInfo data
|
Return Hash of UserInfo data
|
||||||
|
|
||||||
|
=head2 createJWT
|
||||||
|
|
||||||
|
Return JWT
|
||||||
|
|
||||||
=head2 createIDToken
|
=head2 createIDToken
|
||||||
|
|
||||||
Return ID Token
|
Return ID Token
|
||||||
|
|
Loading…
Reference in New Issue
Block a user