Manager UserInfo signature (JWT response) (#184)

This commit is contained in:
Clément Oudot 2015-04-14 18:42:02 +00:00
parent e84963ac32
commit 9520bef489
5 changed files with 102 additions and 70 deletions

View File

@ -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",
}, },
}, },
}, },

View File

@ -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",

View File

@ -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}

View File

@ -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' );

View File

@ -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