Configuration of OpenID Connect auth module and OP in Manager (#183)

This commit is contained in:
Clément Oudot 2014-12-15 13:55:23 +00:00
parent fc1e447aaf
commit 922b92bbbe
11 changed files with 368 additions and 31 deletions

View File

@ -2,7 +2,7 @@ package Lemonldap::NG::Common::Conf::Serializer;
use Data::Dumper;
our $VERSION = '1.4.0';
our $VERSION = 2.00;
BEGIN {
*Lemonldap::NG::Common::Conf::normalize = \&normalize;
@ -122,6 +122,10 @@ sub unserialize {
|logoutServices
|macros
|notificationStorageOptions
|oidcOPMetaDataExportedVars
|oidcOPMetaDataJSON
|oidcOPMetaDataJWKS
|oidcOPMetaDataOptions
|openIdExportedVars
|persistentStorageOptions
|portalSkinRules

View File

@ -8,7 +8,7 @@ package Lemonldap::NG::Common::Conf::SubAttributes;
use Mouse;
our $VERSION = 1.4.1;
our $VERSION = 2.00;
## E
@ -28,6 +28,78 @@ has 'locationRules' => (
documentation => "Rules for a virtual host",
);
## O
has 'oidcOPMetaDataExportedVars' => (
is => 'rw',
isa => 'HashRef',
default => sub { return { 'uid' => 'sub' }; },
documentation => "Exported vars for an OP",
);
has 'oidcOPMetaDataOptionsCheckJWTSignature' => (
is => 'rw',
isa => 'Bool',
default => '1',
documentation => 'OIDC OP JWT signature checking',
);
has 'oidcOPMetaDataOptionsClientID' => (
is => 'rw',
isa => 'Str|Undef',
default => undef,
documentation => "OIDC OP client ID",
);
has 'oidcOPMetaDataOptionsClientSecret' => (
is => 'rw',
isa => 'Str|Undef',
default => undef,
documentation => "OIDC OP client Secret",
);
has 'oidcOPMetaDataOptionsConfigurationURI' => (
is => 'rw',
isa => 'Str|Undef',
default => undef,
documentation => "OIDC OP configuration endpoint",
);
has 'oidcOPMetaDataOptionsDisplayName' => (
is => 'rw',
isa => 'Str',
default => "Provider name",
documentation => "OIDC OP display name",
);
has 'oidcOPMetaDataOptionsIcon' => (
is => 'rw',
isa => 'Str|Undef',
default => undef,
documentation => "OIDC OP logo file",
);
has 'oidcOPMetaDataOptionsJWKSTimeout' => (
is => 'rw',
isa => 'Int',
default => "0",
documentation => "OIDC OP JWKS data refresh interval",
);
has 'oidcOPMetaDataOptionsScope' => (
is => 'rw',
isa => 'Str',
default => "openid email profile",
documentation => "OIDC OP scope",
);
has 'oidcOPMetaDataOptionsTokenEndpointAuthMethod' => (
is => 'rw',
isa => 'Str',
default => "client_secret_basic",
documentation => "OIDC OP scope",
);
## P
has 'post' => (

View File

@ -464,6 +464,7 @@ function display(div, title) {
$('#newapplicationr,#delapplication').hide();
$('#newpostr,#delpost').hide();
$('#newpostdatar,#delpostdata').hide();
$('#newoidcopb,#deloidcopb').hide();
// Resize (or hide) Help window
resizeHelp();
}
@ -491,6 +492,11 @@ function samlSpRoot(id) {
display('default', '');
$('#newspsamlmetadatab').show();
}
function oidcOPRoot(id) {
currentId = id;
display('default', '');
$('#newoidcopb').show();
}
/* @function splitModuleAndOptions(string data)
* Split module and options from authentication or userDB string
* @return module, options
@ -825,6 +831,17 @@ function samlSpMetaData(id) {
}
$('#newspsamlmetadatab').show();
}
function oidcOPMetaData(id) {
currentId = id;
$('#oidcOPMetaData').val(lmtext(id));
display('oidcOPMetaData', lmtext(id));
if ($('#li_' + myB64('/oidcOPMetaDataNode')).find('span').size() == 1) {
$('#deloidcopb').hide();
} else {
$('#deloidcopb').show();
}
$('#newoidcopb').show();
}
function samlService(id) {
currentId = id;
var t = lmdata(id).split(';');
@ -1083,6 +1100,24 @@ function newSpSamlMetaData() {
samlSpMetaData(spId);
});
}
function newOidcOp() {
var name = prompt(text4newOidcOp, 'op-example');
if (!name) {
return false;
}
var opId = 'li_' + myB64('/oidcOPMetaDataExportedVars/' + name);
simpleTreeCollection[0].newAjaxNodeIn($('#li_L29pZGNPUE1ldGFEYXRhTm9kZQ2'), opId, name, scriptname + '?type=new&node=/oidcOPMetaDataNode/' + name, function(d, s) {
$('>span', s).attr('name', name).attr('help', 'default').attr('id', 'text_' + opId).attr('onclick', 'oidcOPMetaData(\'' + opId + '\')');
oidcOPMetaData(opId);
});
}
function delOidcOp(id) {
var opname = lmtext(id);
if (confirm('Delete ' + opname + ' ?')) {
delKey(id);
oidcOPMetaData(id);
}
}
var cfgAttrDone = 0;
function uploadConf(f) {
if (! (f == 1)) f = 0;

View File

@ -52,6 +52,7 @@
var text4newApplication='<lang en="Application identifier" fr="Identifiant de l\'application" />';
var text4newCondition='<lang en="New Condition" fr="Nouvelle Condition" />';
var lang='<TMPL_VAR NAME="LANG">';
var text4newOidcOp='<lang en="Provider name" fr="Nom du fournisseur" />';
//]]></script>
<script src="<TMPL_VAR NAME="DIR">/js/manager.js" type="text/JavaScript"></script>
</head>
@ -255,6 +256,16 @@
<lang en="Delete POST data" fr="Supprimer la donnée POST" />
</button>
<button id="newoidcopb" style="display:none;" onclick="newOidcOp();return false;" class="btn btn-success">
<i class=" glyphicon glyphicon-plus-sign"></i>
<lang en="New provider" fr="Nouveau fournisseur" />
</button>
<button id="deloidcopb" style="display:none;" onclick="delOidcOp(currentId);" class="btn btn-danger">
<i class=" glyphicon glyphicon-minus-sign"></i>
<lang en="Delete provider" fr="Supprimer le fournisseur" />
</button>
</div>
<!-- Buttons -->
@ -817,6 +828,18 @@
</div>
</div>
<!-- oidcOPMetaData -->
<div id="content_oidcOPMetaData" class="hidden">
<input type="text" id="oidcOPMetaData" size="30" class="form-control"/>
<div class="buttons">
<button onclick="setlminputtext(currentId,oidcOPMetaData);return false;" class="btn btn-info">
<i class="glyphicon glyphicon-ok"></i>
<lang en="Apply" fr="Appliquer" />
</button>
</div>
</div>
</div>
</form>

View File

@ -14,7 +14,7 @@ require Lemonldap::NG::Manager::_Struct; #inherits
require Lemonldap::NG::Manager::_i18n; #inherits
require Lemonldap::NG::Manager::Request; #inherits
our $VERSION = '1.4.0';
our $VERSION = 2.00;
## @method string node(string node)
# Build the part of the tree that does not depends of the configuration.
@ -229,6 +229,41 @@ sub confNode {
) . "</li>";
}
# OIDC Metadata
elsif ( $target =~ s/^oidcmetadatajson:// ) {
my $h = $self->keyToH( $target, $self->conf );
$h = $h->{oidcOPMetaDataJSON};
my $text = $target;
$text =~ s/^\/([^\/]+)\/.*$/$1/;
$res .= $self->li("$target/")
. $self->span(
id => "$target/",
text => $text,
data => $h,
js => $js,
help => $help,
target => "oidcmetadatajson",
) . "</li>";
}
elsif ( $target =~ s/^oidcmetadatajwks:// ) {
my $h = $self->keyToH( $target, $self->conf );
$h = $h->{oidcOPMetaDataJWKS};
my $text = $target;
$text =~ s/^\/([^\/]+)\/.*$/$1/;
$res .= $self->li("$target/")
. $self->span(
id => "$target/",
text => $text,
data => $h,
js => $js,
help => $help,
target => "oidcmetadatajwks",
) . "</li>";
}
# Application list
elsif ( $target =~ s/^applicationlist:// ) {
$self->lmLog( "Load applications list (target $target)", 'debug' );

View File

@ -20,7 +20,7 @@ use Lemonldap::NG::Manager::_i18n;
use Lemonldap::NG::Manager::Request;
use Lemonldap::NG::Common::Conf::Constants; #inherits
our $VERSION = '1.4.0';
our $VERSION = 2.00;
our ( $stylesheet, $parser );
## @method void confUpload(ref rdata)
@ -42,6 +42,7 @@ sub confUpload {
my $spname;
my $catid;
my $postname;
my $opname;
# 1. ANALYSE DATAS
@ -110,6 +111,12 @@ s/^text_(NewID_)?li_([\w\/\+\=]+)(\d)(?:_\d+)?$/decode_base64($2.'='x $3)/e;
$spname = $name;
}
# Get OIDC OP name
if ( $id =~ /oidcOPMetaDataExportedVars\/([^\/]*)?$/ ) {
$self->lmLog( "Entering OP $name", 'debug' );
$opname = $name;
}
# Set menu category and application flags
if ( $id =~ /applicationList/ ) {
if ( $value =~ /^(.*)?\|(.*)?\|(.*)?\|(.*)?\|(.*?)$/ ) {
@ -132,7 +139,7 @@ s/^text_(NewID_)?li_([\w\/\+\=]+)(\d)(?:_\d+)?$/decode_base64($2.'='x $3)/e;
# Special case: avoid bug with node created from parent node
if ( $id =~
/^(virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|generalParameters\/authParams\/choiceParams)/
/^(virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|oidcOPMetaDataNode|generalParameters\/authParams\/choiceParams)/
)
{
$self->lmLog( "Special trigger for $id (attribute $name)",
@ -157,6 +164,10 @@ s/^samlIDPMetaDataNode\/([^\/]*)?.*/samlIDPMetaDataExportedAttributes\/$1\/$name
$id =~
s/^samlSPMetaDataNode\/([^\/]*)?.*/samlSPMetaDataExportedAttributes\/$1\/$name/;
# OIDC OP attribute
$id =~
s/^oidcOPMetaDataNode\/([^\/]*)?.*/oidcOPMetaDataExportedVars\/$1\/$name/;
# Authentication choice
$id =~
s/^generalParameters\/authParams\/choiceParams\/([^\/]*)?.*/authChoiceModules\/$name/;
@ -198,13 +209,17 @@ s/^(samlIDPMetaDataXML|samlIDPMetaDataExportedAttributes|samlIDPMetaDataOptions)
$id =~
s/^(samlSPMetaDataXML|samlSPMetaDataExportedAttributes|samlSPMetaDataOptions)\/([^\/]*)?\/(.*)$/$1\/$spname\/$3/;
# Set current OIDC OP name
$id =~
s/^(oidcOPMetaDataJSON|oidcOPMetaDataJWKS|oidcOPMetaDataExportedVars|oidcOPMetaDataOptions)\/([^\/]*)?\/(.*)$/$1\/$opname\/$3/;
# Set current POST URL name
$id =~ s/^(post)\/([^\/]*)?\/(.*)$/$1\/$vhostname\/$postname/;
$self->lmLog( "id transformed into $id", 'debug' );
if ( $id =~
/^(generalParameters|variables|virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode)/
/^(generalParameters|variables|virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|oidcOPMetaDataNode)/
)
{
$self->lmLog( "Ignoring attribute $name (id $id)", 'debug' );

View File

@ -11,7 +11,7 @@ use Lemonldap::NG::Common::Conf::Attributes;
use Lemonldap::NG::Common::Conf::SubAttributes;
use Lemonldap::NG::Common::Regexp;
our $VERSION = '2.00';
our $VERSION = 2.00;
## @method protected hashref cstruct(hashref h,string k)
# Merge $h with the structure produced with $k and return it.
@ -249,6 +249,69 @@ sub cstruct {
}
);
}
elsif ( $k1 =~ /^oidcOPMetaDataNode/i ) {
%$h = (
%$h,
oidcOPMetaDataNode => {
$k2 => {
_nodes => [
qw(oidcOPMetaDataJSON oidcOPMetaDataJWKS oidcOPMetaDataExportedVars oidcOPMetaDataOptions)
],
oidcOPMetaDataJSON =>
"oidcmetadatajson:/oidcOPMetaDataJSON/$k2:oidcOPMetaDataJSON:textarea",
oidcOPMetaDataJWKS =>
"oidcmetadatajwks:/oidcOPMetaDataJWKS/$k2:oidcOPMetaDataJWKS:textarea",
oidcOPMetaDataExportedVars => {
_nodes =>
["hash:/oidcOPMetaDataExportedVars/$k2:vars:btext"],
_js => 'hashRoot',
},
oidcOPMetaDataOptions => {
_nodes => [
qw(oidcOPMetaDataOptionsConfiguration oidcOPMetaDataOptionsProtocol oidcOPMetaDataOptionsDisplay)
],
oidcOPMetaDataOptionsConfiguration => {
_nodes => [
qw(oidcOPMetaDataOptionsConfigurationURI oidcOPMetaDataOptionsJWKSTimeout oidcOPMetaDataOptionsClientID oidcOPMetaDataOptionsClientSecret)
],
oidcOPMetaDataOptionsConfigurationURI =>
"text:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsConfigurationURI",
oidcOPMetaDataOptionsJWKSTimeout =>
"int:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsJWKSTimeout",
oidcOPMetaDataOptionsClientID =>
"text:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsClientID",
oidcOPMetaDataOptionsClientSecret =>
"text:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsClientSecret",
},
oidcOPMetaDataOptionsProtocol => {
_nodes => [
qw(oidcOPMetaDataOptionsScope oidcOPMetaDataOptionsTokenEndpointAuthMethod oidcOPMetaDataOptionsCheckJWTSignature)
],
oidcOPMetaDataOptionsScope =>
"text:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsScope",
oidcOPMetaDataOptionsTokenEndpointAuthMethod =>
"text:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsTokenEndpointAuthMethod",
oidcOPMetaDataOptionsCheckJWTSignature =>
"bool:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsCheckJWTSignature",
},
oidcOPMetaDataOptionsDisplay => {
_nodes => [
qw(oidcOPMetaDataOptionsDisplayName oidcOPMetaDataOptionsIcon)
],
oidcOPMetaDataOptionsDisplayName =>
"text:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsDisplayName",
oidcOPMetaDataOptionsIcon =>
"text:/oidcOPMetaDataOptions/$k2/oidcOPMetaDataOptionsIcon",
},
},
},
},
);
}
return $h;
}
@ -259,7 +322,7 @@ sub struct {
my $self = shift;
return {
_nodes => [
qw(n:generalParameters n:variables n:virtualHosts n:samlServiceMetaData n:samlIDPMetaDataNode n:samlSPMetaDataNode)
qw(n:generalParameters n:variables n:virtualHosts n:samlServiceMetaData n:samlIDPMetaDataNode n:samlSPMetaDataNode n:oidcOPMetaDataNode)
],
_help => 'default',
@ -1461,6 +1524,22 @@ sub struct {
},
},
########
# OIDC #
########
oidcOPMetaDataNode => {
_nodes => [
'nhash:/oidcOPMetaDataExportedVars:oidcOPMetaDataNode:oidcOPMetaData'
],
_upload => [
'/oidcOPMetaDataJSON', '/oidcOPMetaDataJWKS',
'/oidcOPMetaDataOptions'
],
_help => 'oidcOP',
_js => 'oidcOPRoot',
},
};
}
@ -2174,6 +2253,42 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
browserIdSiteName => $testNotDefined,
browserIdSiteLogo => $testNotDefined,
browserIdBackgroundColor => $testNotDefined,
# OIDC OP
oidcOPMetaDataExportedVars => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
keyTest => qr/^\w([\w\-]*\w)?$/,
keyMsgFail => 'Bad attribute name',
test => sub { return 1; },
},
},
oidcOPMetaDataJSON => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
test => sub { return 1; },
keyTest => sub { return 1; },
},
},
oidcOPMetaDataJWKS => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
test => sub { return 1; },
keyTest => sub { return 1; },
},
},
oidcOPMetaDataOptions => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
test => sub { return 1; },
keyTest => sub { return 1; },
},
},
};
}
## @method hashref subDefaultConf()

View File

@ -254,14 +254,32 @@ sub en {
notificationNotPurged => 'The notification was not definitely removed',
notificationPurged => 'Notification has been definitely removed',
notificationStorage => 'Storage module',
notificationStorageOptions => 'Storage module parameters',
notificationWildcard => 'Wildcard for all users',
notificationXSLTfile => 'Custom XSLT file',
notifyDeleted => 'Display deleted sessions',
notifyOther => 'Display other sessions',
nullAuthnLevel => 'Authentication level',
nullParams => 'Null parameters',
oidcAuthnLevel => 'Authentication level',
notificationStorageOptions => 'Storage module parameters',
notificationWildcard => 'Wildcard for all users',
notificationXSLTfile => 'Custom XSLT file',
notifyDeleted => 'Display deleted sessions',
notifyOther => 'Display other sessions',
nullAuthnLevel => 'Authentication level',
nullParams => 'Null parameters',
oidcAuthnLevel => 'Authentication level',
oidcOPMetaDataExportedVars => 'Exported attributes',
oidcOPMetaDataJSON => 'Metadata',
oidcOPMetaDataJWKS => 'JWKS data',
oidcOPMetaDataNode => 'OpenID Connect Providers',
oidcOPMetaDataOptions => 'Options',
oidcOPMetaDataOptionsCheckJWTSignature => 'Check JWT signature',
oidcOPMetaDataOptionsClientID => 'Client ID',
oidcOPMetaDataOptionsClientSecret => 'Client secret',
oidcOPMetaDataOptionsConfiguration => 'Configuration',
oidcOPMetaDataOptionsConfigurationURI => 'Configuration endpoint',
oidcOPMetaDataOptionsDisplay => 'Display',
oidcOPMetaDataOptionsDisplayName => 'Display name',
oidcOPMetaDataOptionsIcon => 'Logo',
oidcOPMetaDataOptionsJWKSTimeout => 'JWKS data timeout',
oidcOPMetaDataOptionsProtocol => 'Protocol',
oidcOPMetaDataOptionsScope => 'Scope',
oidcOPMetaDataOptionsTokenEndpointAuthMethod =>
'Token endpoint authentication method',
oidcParams => 'OpenID Connect parameters',
oidcRPCallbackGetParam => 'Callback GET parameter',
oidcRPStateTimeout => 'State session timeout',
@ -769,15 +787,34 @@ sub fr {
"La notification n'a pas été définitivement supprimée",
notificationPurged =>
'La notification a été définitivement supprimée',
notificationStorage => 'Module de stockage',
notificationStorageOptions => 'Paramètres du module de stockage',
notificationWildcard => 'Identifiant pour tous les utilisateurs',
notificationXSLTfile => 'Fichier XSLT personnalisé',
notifyDeleted => 'Affiche les sessions effacées',
notifyOther => 'Affiche les autres sessions',
nullAuthnLevel => 'Niveau d\'authentification',
nullParams => 'Paramètres Null',
oidcAuthnLevel => 'Niveau d\'authentification',
notificationStorage => 'Module de stockage',
notificationStorageOptions => 'Paramètres du module de stockage',
notificationWildcard => 'Identifiant pour tous les utilisateurs',
notificationXSLTfile => 'Fichier XSLT personnalisé',
notifyDeleted => 'Affiche les sessions effacées',
notifyOther => 'Affiche les autres sessions',
nullAuthnLevel => 'Niveau d\'authentification',
nullParams => 'Paramètres Null',
oidcAuthnLevel => 'Niveau d\'authentification',
oidcOPMetaDataExportedVars => 'Attributs exportés',
oidcOPMetaDataJSON => 'Métadonnées',
oidcOPMetaDataJWKS => 'Données JWKS',
oidcOPMetaDataNode => 'Fournisseurs OpenID Connect',
oidcOPMetaDataOptions => 'Options',
oidcOPMetaDataOptionsCheckJWTSignature =>
'Vérifier la signature des jetons',
oidcOPMetaDataOptionsClientID => 'Identifiant',
oidcOPMetaDataOptionsClientSecret => 'Mot de passe',
oidcOPMetaDataOptionsConfiguration => 'Configuration',
oidcOPMetaDataOptionsConfigurationURI => 'URI de la configuration',
oidcOPMetaDataOptionsDisplay => 'Affichage',
oidcOPMetaDataOptionsDisplayName => 'Nom d\'affichage',
oidcOPMetaDataOptionsIcon => 'Logo',
oidcOPMetaDataOptionsJWKSTimeout => 'Durée de vie des données JWKS',
oidcOPMetaDataOptionsProtocol => 'Protocole',
oidcOPMetaDataOptionsScope => 'Étendue',
oidcOPMetaDataOptionsTokenEndpointAuthMethod =>
'Méthode d\'authentification pour l\'accès aux jetons',
oidcParams => 'Paramètres OpenID Connect',
oidcRPCallbackGetParam => 'Paramètre GET callback',
oidcRPStateTimeout => 'Durée d\'une session state',

View File

@ -10,7 +10,7 @@ use Lemonldap::NG::Portal::Simple;
use MIME::Base64;
use base qw(Lemonldap::NG::Portal::_OpenIDConnect);
our $VERSION = '2.00';
our $VERSION = 2.00;
## @apmethod int authInit()
# Get configuration data

View File

@ -9,7 +9,7 @@ use strict;
use Lemonldap::NG::Portal::Simple;
our @ISA = (qw(Lemonldap::NG::Portal::_OpenIDConnect));
our $VERSION = '2.00';
our $VERSION = 2.00;
## @apmethod int userDBInit()
# Do nothing

View File

@ -15,7 +15,7 @@ use Crypt::OpenSSL::RSA;
use Crypt::OpenSSL::Bignum;
use base qw(Lemonldap::NG::Portal::_Browser);
our $VERSION = '2.00';
our $VERSION = 2.00;
our $oidcCache;
BEGIN {
@ -53,9 +53,11 @@ sub loadOPs {
$self->{_oidcOPList} = {};
foreach ( keys %{ $self->{oidcOPMetaDataJSON} } ) {
$self->{_oidcOPList}->{$_}->{conf} =
$self->decodeJSON( $self->{oidcOPMetaDataJSON}->{$_} );
$self->decodeJSON(
$self->{oidcOPMetaDataJSON}->{$_}->{oidcOPMetaDataJSON} );
$self->{_oidcOPList}->{$_}->{jwks} =
$self->decodeJSON( $self->{oidcOPMetaDataJWKS}->{$_} );
$self->decodeJSON(
$self->{oidcOPMetaDataJWKS}->{$_}->{oidcOPMetaDataJWKS} );
}
$oidcCache->{_oidcOPList} = $self->{_oidcOPList} unless $no_cache;
@ -206,7 +208,6 @@ sub buildAuthorizationCodeAuthnRequest {
# return String Token response decoded content
sub getAuthorizationCodeAccessToken {
my ( $self, $op, $code, $auth_method ) = splice @_;
$auth_method ||= "client_secret_basic";
my $client_id =
$self->{oidcOPMetaDataOptions}->{$op}->{oidcOPMetaDataOptionsClientID};