Start of registration endpoint implementation (#184)
This commit is contained in:
parent
b14ec43a88
commit
2e0f1b7088
|
@ -774,6 +774,13 @@ has 'oidcServiceMetaDataJWKSURI' => (
|
||||||
documentation => 'OpenID Connect JWKS endpoint',
|
documentation => 'OpenID Connect JWKS endpoint',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
has 'oidcServiceMetaDataRegistrationURI' => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Str',
|
||||||
|
default => 'register',
|
||||||
|
documentation => 'OpenID Connect registration endpoint',
|
||||||
|
);
|
||||||
|
|
||||||
has 'oidcServiceMetaDataTokenURI' => (
|
has 'oidcServiceMetaDataTokenURI' => (
|
||||||
is => 'rw',
|
is => 'rw',
|
||||||
isa => 'Str',
|
isa => 'Str',
|
||||||
|
|
|
@ -316,9 +316,8 @@ sub cstruct {
|
||||||
%$h,
|
%$h,
|
||||||
oidcRPMetaDataNode => {
|
oidcRPMetaDataNode => {
|
||||||
$k2 => {
|
$k2 => {
|
||||||
_nodes => [
|
_nodes =>
|
||||||
qw(oidcRPMetaDataExportedVars oidcRPMetaDataOptions)
|
[ qw(oidcRPMetaDataExportedVars oidcRPMetaDataOptions) ],
|
||||||
],
|
|
||||||
oidcRPMetaDataExportedVars => {
|
oidcRPMetaDataExportedVars => {
|
||||||
_nodes =>
|
_nodes =>
|
||||||
["hash:/oidcRPMetaDataExportedVars/$k2:vars:btext"],
|
["hash:/oidcRPMetaDataExportedVars/$k2:vars:btext"],
|
||||||
|
@ -328,24 +327,24 @@ sub cstruct {
|
||||||
_nodes => [
|
_nodes => [
|
||||||
qw(oidcRPMetaDataOptionsAuthentication oidcRPMetaDataOptionsDisplay oidcRPMetaDataOptionsUserIDAttr oidcRPMetaDataOptionsIDTokenSignAlg oidcRPMetaDataOptionsIDTokenExpiration oidcRPMetaDataOptionsAccessTokenExpiration oidcRPMetaDataOptionsRedirectUris)
|
qw(oidcRPMetaDataOptionsAuthentication oidcRPMetaDataOptionsDisplay oidcRPMetaDataOptionsUserIDAttr oidcRPMetaDataOptionsIDTokenSignAlg oidcRPMetaDataOptionsIDTokenExpiration oidcRPMetaDataOptionsAccessTokenExpiration oidcRPMetaDataOptionsRedirectUris)
|
||||||
],
|
],
|
||||||
oidcRPMetaDataOptionsAuthentication => {
|
oidcRPMetaDataOptionsAuthentication => {
|
||||||
_nodes => [
|
_nodes => [
|
||||||
qw(oidcRPMetaDataOptionsClientID oidcRPMetaDataOptionsClientSecret)
|
qw(oidcRPMetaDataOptionsClientID oidcRPMetaDataOptionsClientSecret)
|
||||||
],
|
],
|
||||||
oidcRPMetaDataOptionsClientID =>
|
oidcRPMetaDataOptionsClientID =>
|
||||||
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsClientID",
|
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsClientID",
|
||||||
oidcRPMetaDataOptionsClientSecret =>
|
oidcRPMetaDataOptionsClientSecret =>
|
||||||
"password:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsClientSecret",
|
"password:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsClientSecret",
|
||||||
},
|
},
|
||||||
oidcRPMetaDataOptionsDisplay => {
|
oidcRPMetaDataOptionsDisplay => {
|
||||||
_nodes => [
|
_nodes => [
|
||||||
qw(oidcRPMetaDataOptionsDisplayName oidcRPMetaDataOptionsIcon)
|
qw(oidcRPMetaDataOptionsDisplayName oidcRPMetaDataOptionsIcon)
|
||||||
],
|
],
|
||||||
oidcRPMetaDataOptionsDisplayName =>
|
oidcRPMetaDataOptionsDisplayName =>
|
||||||
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsDisplayName",
|
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsDisplayName",
|
||||||
oidcRPMetaDataOptionsIcon =>
|
oidcRPMetaDataOptionsIcon =>
|
||||||
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsIcon",
|
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsIcon",
|
||||||
},
|
},
|
||||||
oidcRPMetaDataOptionsUserIDAttr =>
|
oidcRPMetaDataOptionsUserIDAttr =>
|
||||||
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsUserIDAttr",
|
"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsUserIDAttr",
|
||||||
oidcRPMetaDataOptionsIDTokenSignAlg =>
|
oidcRPMetaDataOptionsIDTokenSignAlg =>
|
||||||
|
@ -1601,7 +1600,7 @@ sub struct {
|
||||||
|
|
||||||
oidcServiceMetaDataEndPoints => {
|
oidcServiceMetaDataEndPoints => {
|
||||||
_nodes => [
|
_nodes => [
|
||||||
qw(oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI)
|
qw(oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI)
|
||||||
],
|
],
|
||||||
|
|
||||||
oidcServiceMetaDataAuthorizeURI =>
|
oidcServiceMetaDataAuthorizeURI =>
|
||||||
|
@ -1612,6 +1611,8 @@ sub struct {
|
||||||
'text:/oidcServiceMetaDataUserInfoURI',
|
'text:/oidcServiceMetaDataUserInfoURI',
|
||||||
oidcServiceMetaDataJWKSURI =>
|
oidcServiceMetaDataJWKSURI =>
|
||||||
'text:/oidcServiceMetaDataJWKSURI',
|
'text:/oidcServiceMetaDataJWKSURI',
|
||||||
|
oidcServiceMetaDataRegistrationURI =>
|
||||||
|
'text:/oidcServiceMetaDataRegistrationURI',
|
||||||
},
|
},
|
||||||
|
|
||||||
oidcServiceMetaDataSecurity => {
|
oidcServiceMetaDataSecurity => {
|
||||||
|
|
|
@ -306,6 +306,7 @@ sub en {
|
||||||
oidcServiceMetaDataEndPoints => 'End points',
|
oidcServiceMetaDataEndPoints => 'End points',
|
||||||
oidcServiceMetaDataIssuer => 'Issuer identifier',
|
oidcServiceMetaDataIssuer => 'Issuer identifier',
|
||||||
oidcServiceMetaDataJWKSURI => 'JWKS',
|
oidcServiceMetaDataJWKSURI => 'JWKS',
|
||||||
|
oidcServiceMetaDataRegistrationURI => 'Registration',
|
||||||
oidcServiceMetaDataSecurity => 'Security',
|
oidcServiceMetaDataSecurity => 'Security',
|
||||||
oidcServiceMetaDataTokenURI => 'Token',
|
oidcServiceMetaDataTokenURI => 'Token',
|
||||||
oidcServiceMetaDataUserInfoURI => 'User Info',
|
oidcServiceMetaDataUserInfoURI => 'User Info',
|
||||||
|
@ -864,41 +865,42 @@ 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",
|
||||||
oidcRPStateTimeout => 'Durée d\'une session state',
|
oidcRPStateTimeout => 'Durée d\'une session state',
|
||||||
oidcServiceMetaData => "Service OpenID Connect",
|
oidcServiceMetaData => "Service OpenID Connect",
|
||||||
oidcServiceMetaDataAuthorizeURI => "Autorisation",
|
oidcServiceMetaDataAuthorizeURI => "Autorisation",
|
||||||
oidcServiceMetaDataEndPoints => "Points d'accès",
|
oidcServiceMetaDataEndPoints => "Points d'accès",
|
||||||
oidcServiceMetaDataIssuer => "Identifiant du fournisseur",
|
oidcServiceMetaDataIssuer => "Identifiant du fournisseur",
|
||||||
oidcServiceMetaDataJWKSURI => 'JWKS',
|
oidcServiceMetaDataJWKSURI => 'JWKS',
|
||||||
oidcServiceMetaDataSecurity => 'Sécurité',
|
oidcServiceMetaDataRegistrationURI => 'Enregistrement',
|
||||||
oidcServiceMetaDataTokenURI => "Jeton",
|
oidcServiceMetaDataSecurity => 'Sécurité',
|
||||||
oidcServiceMetaDataUserInfoURI => 'Informations Utilisateur',
|
oidcServiceMetaDataTokenURI => "Jeton",
|
||||||
oidcServicePrivateKeySig => 'Clé privée de signature',
|
oidcServiceMetaDataUserInfoURI => 'Informations Utilisateur',
|
||||||
oidcServicePublicKeySig => 'Clé publique de signature',
|
oidcServicePrivateKeySig => 'Clé privée de signature',
|
||||||
openIdAttr => 'Identifiant OpenID',
|
oidcServicePublicKeySig => 'Clé publique de signature',
|
||||||
openIdAuthnLevel => 'Niveau d\'authentification',
|
openIdAttr => 'Identifiant OpenID',
|
||||||
openIdExportedVars => 'Variables exportées',
|
openIdAuthnLevel => 'Niveau d\'authentification',
|
||||||
openIdIDPList => 'Domaines autorisés',
|
openIdExportedVars => 'Variables exportées',
|
||||||
openIdIssuerSecret => 'Jeton secret',
|
openIdIDPList => 'Domaines autorisés',
|
||||||
openIdParams => 'Paramètres OpenID',
|
openIdIssuerSecret => 'Jeton secret',
|
||||||
openIdSecret => 'Jeton secret',
|
openIdParams => 'Paramètres OpenID',
|
||||||
openIdSreg => 'Associations SREG',
|
openIdSecret => 'Jeton secret',
|
||||||
openIdSreg_fullname => 'Nom complet',
|
openIdSreg => 'Associations SREG',
|
||||||
openIdSreg_nickname => 'Surnom',
|
openIdSreg_fullname => 'Nom complet',
|
||||||
openIdSreg_language => 'Langage',
|
openIdSreg_nickname => 'Surnom',
|
||||||
openIdSreg_postcode => 'Code postal',
|
openIdSreg_language => 'Langage',
|
||||||
openIdSreg_timezone => 'Zone horaire',
|
openIdSreg_postcode => 'Code postal',
|
||||||
openIdSreg_country => 'Pays',
|
openIdSreg_timezone => 'Zone horaire',
|
||||||
openIdSreg_gender => 'Genre',
|
openIdSreg_country => 'Pays',
|
||||||
openIdSreg_email => 'Email',
|
openIdSreg_gender => 'Genre',
|
||||||
openIdSreg_dob => 'Date de naissance',
|
openIdSreg_email => 'Email',
|
||||||
openIdSPList => 'Domaines autorisés',
|
openIdSreg_dob => 'Date de naissance',
|
||||||
passwordDB => 'Module de mot de passe',
|
openIdSPList => 'Domaines autorisés',
|
||||||
passwordManagement => 'Gestion des mots de passe',
|
passwordDB => 'Module de mot de passe',
|
||||||
persistentSessions => 'Sessions persistantes',
|
passwordManagement => 'Gestion des mots de passe',
|
||||||
persistentStorage => 'Module Apache::Session',
|
persistentSessions => 'Sessions persistantes',
|
||||||
|
persistentStorage => 'Module Apache::Session',
|
||||||
persistentStorageOptions => 'Paramètres du module Apache::Session',
|
persistentStorageOptions => 'Paramètres du module Apache::Session',
|
||||||
port => 'Port',
|
port => 'Port',
|
||||||
portal => 'URL',
|
portal => 'URL',
|
||||||
|
|
|
@ -11,6 +11,7 @@ my $authorize_uri = $portal->{oidcServiceMetaDataAuthorizeURI};
|
||||||
my $token_uri = $portal->{oidcServiceMetaDataTokenURI};
|
my $token_uri = $portal->{oidcServiceMetaDataTokenURI};
|
||||||
my $userinfo_uri = $portal->{oidcServiceMetaDataUserInfoURI};
|
my $userinfo_uri = $portal->{oidcServiceMetaDataUserInfoURI};
|
||||||
my $jwks_uri = $portal->{oidcServiceMetaDataJWKSURI};
|
my $jwks_uri = $portal->{oidcServiceMetaDataJWKSURI};
|
||||||
|
my $registration_uri = $portal->{oidcServiceMetaDataRegistrationURI};
|
||||||
|
|
||||||
my ($path) = ( $issuerDBOpenIDConnectPath =~ /(\w+)/ );
|
my ($path) = ( $issuerDBOpenIDConnectPath =~ /(\w+)/ );
|
||||||
my $issuer = $portal->{oidcServiceMetaDataIssuer};
|
my $issuer = $portal->{oidcServiceMetaDataIssuer};
|
||||||
|
@ -23,8 +24,8 @@ $configuration->{authorization_endpoint} =
|
||||||
$configuration->{token_endpoint} = $issuer . $path . "/" . $token_uri;
|
$configuration->{token_endpoint} = $issuer . $path . "/" . $token_uri;
|
||||||
$configuration->{userinfo_endpoint} = $issuer . $path . "/" . $userinfo_uri;
|
$configuration->{userinfo_endpoint} = $issuer . $path . "/" . $userinfo_uri;
|
||||||
$configuration->{jwks_uri} = $issuer . $path . "/" . $jwks_uri;
|
$configuration->{jwks_uri} = $issuer . $path . "/" . $jwks_uri;
|
||||||
|
$configuration->{registration_endpoint} =
|
||||||
# RECOMMENDED # $configuration->{registration_endpoint}
|
$issuer . $path . "/" . $registration_uri;
|
||||||
$configuration->{scopes_supported} = [qw/openid profile email address phone/];
|
$configuration->{scopes_supported} = [qw/openid profile email address phone/];
|
||||||
$configuration->{response_types_supported} = [
|
$configuration->{response_types_supported} = [
|
||||||
"code",
|
"code",
|
||||||
|
|
|
@ -7,6 +7,7 @@ package Lemonldap::NG::Portal::IssuerDBOpenIDConnect;
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use Lemonldap::NG::Portal::Simple;
|
use Lemonldap::NG::Portal::Simple;
|
||||||
|
use String::Random qw(random_string);
|
||||||
use base qw(Lemonldap::NG::Portal::_OpenIDConnect);
|
use base qw(Lemonldap::NG::Portal::_OpenIDConnect);
|
||||||
|
|
||||||
our $VERSION = '2.00';
|
our $VERSION = '2.00';
|
||||||
|
@ -34,6 +35,7 @@ sub issuerForUnAuthUser {
|
||||||
my $token_uri = $self->{oidcServiceMetaDataTokenURI};
|
my $token_uri = $self->{oidcServiceMetaDataTokenURI};
|
||||||
my $userinfo_uri = $self->{oidcServiceMetaDataUserInfoURI};
|
my $userinfo_uri = $self->{oidcServiceMetaDataUserInfoURI};
|
||||||
my $jwks_uri = $self->{oidcServiceMetaDataJWKSURI};
|
my $jwks_uri = $self->{oidcServiceMetaDataJWKSURI};
|
||||||
|
my $registration_uri = $self->{oidcServiceMetaDataRegistrationURI};
|
||||||
my $issuer = $self->{oidcServiceMetaDataIssuer};
|
my $issuer = $self->{oidcServiceMetaDataIssuer};
|
||||||
|
|
||||||
# Called URL
|
# Called URL
|
||||||
|
@ -356,6 +358,71 @@ sub issuerForUnAuthUser {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# REGISTRATION
|
||||||
|
if ( $url_path =~ m#${issuerDBOpenIDConnectPath}${registration_uri}# ) {
|
||||||
|
|
||||||
|
$self->lmLog( "URL $url detected as an OpenID Connect REGISTRATION URL",
|
||||||
|
'debug' );
|
||||||
|
|
||||||
|
# TODO: check Initial Access Token
|
||||||
|
|
||||||
|
# Specific message to allow DOS detection
|
||||||
|
my $source_ip = $self->ipAddr;
|
||||||
|
$self->lmLog( "OpenID Connect Registration request from $source_ip",
|
||||||
|
'warn' );
|
||||||
|
|
||||||
|
# Get client metadata
|
||||||
|
my $client_metadata_json = $self->param('POSTDATA');
|
||||||
|
|
||||||
|
$self->lmLog( "Client metadata received: $client_metadata_json",
|
||||||
|
'debug' );
|
||||||
|
|
||||||
|
my $client_metadata = $self->decodeJSON($client_metadata_json);
|
||||||
|
my $registration_response = {};
|
||||||
|
|
||||||
|
# Check redirect_uris
|
||||||
|
unless ( $client_metadata->{redirect_uris} ) {
|
||||||
|
$self->lmLog( "Field redirect_uris is mandatory", 'error' );
|
||||||
|
$self->returnJSONError( 'invalid_client_metadata',
|
||||||
|
'Field redirect_uris is mandatory' );
|
||||||
|
$self->quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
# RP identifier
|
||||||
|
my $registration_time = time;
|
||||||
|
my $rp = "register-$registration_time";
|
||||||
|
|
||||||
|
# Generate Client ID and Client Password
|
||||||
|
my $client_id = random_string("...............");
|
||||||
|
my $client_secret = random_string("...............");
|
||||||
|
|
||||||
|
# Register known parameters
|
||||||
|
my $client_name =
|
||||||
|
$client_metadata->{client_name} || "Self registered client";
|
||||||
|
my $logo_uri = $client_metadata->{logo_uri};
|
||||||
|
my $id_token_signed_response_alg =
|
||||||
|
$client_metadata->{id_token_signed_response_alg} || "RS256";
|
||||||
|
|
||||||
|
# TODO: register RP in global configuration
|
||||||
|
|
||||||
|
# Send registration response
|
||||||
|
$registration_response->{'client_id'} = $client_id;
|
||||||
|
$registration_response->{'client_secret'} = $client_secret;
|
||||||
|
$registration_response->{'client_id_issued_at'} = $registration_time;
|
||||||
|
$registration_response->{'client_id_expires_at'} = 0;
|
||||||
|
$registration_response->{'client_name'} = $client_name;
|
||||||
|
$registration_response->{'logo_uri'} = $logo_uri;
|
||||||
|
$registration_response->{'id_token_signed_response_alg'} =
|
||||||
|
$id_token_signed_response_alg;
|
||||||
|
|
||||||
|
# TODO: return 201 HTTP code
|
||||||
|
$self->returnJSON($registration_response);
|
||||||
|
|
||||||
|
$self->lmLog( "Registration response sent", 'debug' );
|
||||||
|
|
||||||
|
$self->quit;
|
||||||
|
}
|
||||||
|
|
||||||
PE_OK;
|
PE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +438,7 @@ sub issuerForAuthUser {
|
||||||
my $token_uri = $self->{issuerDBOpenIDConnectTokenURI};
|
my $token_uri = $self->{issuerDBOpenIDConnectTokenURI};
|
||||||
my $userinfo_uri = $self->{issuerDBOpenIDConnectUserInfoURI};
|
my $userinfo_uri = $self->{issuerDBOpenIDConnectUserInfoURI};
|
||||||
my $jwks_uri = $self->{oidcServiceMetaDataJWKSURI};
|
my $jwks_uri = $self->{oidcServiceMetaDataJWKSURI};
|
||||||
|
my $registration_uri = $self->{oidcServiceMetaDataRegistrationURI};
|
||||||
my $issuer = $self->{oidcServiceMetaDataIssuer};
|
my $issuer = $self->{oidcServiceMetaDataIssuer};
|
||||||
|
|
||||||
# Session ID
|
# Session ID
|
||||||
|
@ -989,6 +1057,22 @@ sub issuerForAuthUser {
|
||||||
$self->quit;
|
$self->quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# REGISTRATION
|
||||||
|
if ( $url_path =~ m#${issuerDBOpenIDConnectPath}${registration_uri}# ) {
|
||||||
|
|
||||||
|
$self->lmLog( "URL $url detected as an OpenID Connect REGISTRATION URL",
|
||||||
|
'debug' );
|
||||||
|
|
||||||
|
# This should not happen
|
||||||
|
$self->lmLog(
|
||||||
|
"Registration request found on an active SSO session, ignoring it",
|
||||||
|
'error'
|
||||||
|
);
|
||||||
|
$self->returnJSONError("invalid_request");
|
||||||
|
|
||||||
|
$self->quit;
|
||||||
|
}
|
||||||
|
|
||||||
PE_OK;
|
PE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user