Implement OIDC Offline sessions through refresh tokens (#813)

This commit is contained in:
Maxime Besson 2019-10-02 11:37:52 +02:00
parent c01c26af6a
commit ea2365cc98
34 changed files with 794 additions and 260 deletions

View File

@ -24,7 +24,7 @@ use constant MANAGERSECTION => "manager";
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
use constant APPLYSECTION => "apply";
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions)|A(?:ppMetaData(?:(?:ExportedVar|Option)s|Node)|ttributes))|(?:ustomAddParam|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|RPMetaDataOptions(?:LogoutSessionRequired|BypassConsent|RequirePKCE|Public)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|rsEnabled)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?)?|y(?:Deleted|Other))|AjaxHook)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|d(?:isablePersistentStorage|biDynamicHashEnabled|ontCompactConf)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|rest(?:(?:Session|Config)Server|ExportSecretKeys)|br(?:owsersDontStorePassword|uteForceProtection)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:LogoutSessionRequired|BypassConsent|AllowOffline|RequirePKCE|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration|Offline)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|rsEnabled)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?)?|y(?:Deleted|Other))|AjaxHook)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|d(?:isablePersistentStorage|biDynamicHashEnabled|ontCompactConf)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|rest(?:(?:Session|Config)Server|ExportSecretKeys)|br(?:owsersDontStorePassword|uteForceProtection)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );

View File

@ -166,14 +166,17 @@ sub defaultValues {
'notificationStorageOptions' => {
'dirName' => '/var/lib/lemonldap-ng/notifications'
},
'notificationWildcard' => 'allusers',
'notifyDeleted' => 1,
'nullAuthnLevel' => 0,
'oidcAuthnLevel' => 1,
'oidcRPCallbackGetParam' => 'openidconnectcallback',
'oidcRPStateTimeout' => 600,
'oidcServiceAllowAuthorizationCodeFlow' => 1,
'oidcServiceMetaDataAuthnContext' => {
'notificationWildcard' => 'allusers',
'notifyDeleted' => 1,
'nullAuthnLevel' => 0,
'oidcAuthnLevel' => 1,
'oidcRPCallbackGetParam' => 'openidconnectcallback',
'oidcRPStateTimeout' => 600,
'oidcServiceAccessTokenExpiration' => 3600,
'oidcServiceAllowAuthorizationCodeFlow' => 1,
'oidcServiceAuthorizationCodeExpiration' => 60,
'oidcServiceIDTokenExpiration' => 3600,
'oidcServiceMetaDataAuthnContext' => {
'loa-1' => 1,
'loa-2' => 2,
'loa-3' => 3,
@ -190,6 +193,7 @@ sub defaultValues {
'oidcServiceMetaDataRegistrationURI' => 'register',
'oidcServiceMetaDataTokenURI' => 'token',
'oidcServiceMetaDataUserInfoURI' => 'userinfo',
'oidcServiceRefreshTokenExpiration' => 2592000,
'openIdAuthnLevel' => 1,
'openIdExportedVars' => {},
'openIdIDPList' => '0;',

View File

@ -27,7 +27,7 @@ our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaData
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:UserAttribut|Servic|Rul)e|ExportedVars)';
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';
our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))';
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:I(?:DToken(?:Expiration|SignAlg)|con)|Logout(?:SessionRequired|Type|Url)|R(?:e(?:directUris|quirePKCE)|ule)|P(?:ostLogoutRedirectUris|ublic)|AccessTokenExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|ExportedVars)';
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:A(?:(?:uthorizationCode|ccessToken)Expiration|llowOffline)|R(?:e(?:freshTokenExpiration|directUris|quirePKCE)|ule)|I(?:DToken(?:Expiration|SignAlg)|con)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|ExportedVars)';
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ignS[LS]OMessage|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|ExportedAttributes|XML)';
our $virtualHostKeys = '(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
@ -68,6 +68,6 @@ our $issuerParameters = {
issuerOptions => [qw(issuersTimeout)],
};
our $samlServiceParameters = [qw(samlEntityID samlServicePrivateKeySig samlServicePrivateKeySigPwd samlServicePublicKeySig samlServicePrivateKeyEnc samlServicePrivateKeyEncPwd samlServicePublicKeyEnc samlServiceUseCertificateInResponse samlServiceSignatureMethod samlNameIDFormatMapEmail samlNameIDFormatMapX509 samlNameIDFormatMapWindows samlNameIDFormatMapKerberos samlAuthnContextMapPassword samlAuthnContextMapPasswordProtectedTransport samlAuthnContextMapTLSClient samlAuthnContextMapKerberos samlOrganizationDisplayName samlOrganizationName samlOrganizationURL samlSPSSODescriptorAuthnRequestsSigned samlSPSSODescriptorWantAssertionsSigned samlSPSSODescriptorSingleLogoutServiceHTTPRedirect samlSPSSODescriptorSingleLogoutServiceHTTPPost samlSPSSODescriptorSingleLogoutServiceSOAP samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact samlSPSSODescriptorAssertionConsumerServiceHTTPPost samlSPSSODescriptorArtifactResolutionServiceArtifact samlIDPSSODescriptorWantAuthnRequestsSigned samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect samlIDPSSODescriptorSingleSignOnServiceHTTPPost samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect samlIDPSSODescriptorSingleLogoutServiceHTTPPost samlIDPSSODescriptorSingleLogoutServiceSOAP samlIDPSSODescriptorArtifactResolutionServiceArtifact samlAttributeAuthorityDescriptorAttributeServiceSOAP samlMetadataForceUTF8 samlStorage samlStorageOptions samlRelayStateTimeout samlUseQueryStringSpecific samlCommonDomainCookieActivation samlCommonDomainCookieDomain samlCommonDomainCookieReader samlCommonDomainCookieWriter samlDiscoveryProtocolActivation samlDiscoveryProtocolURL samlDiscoveryProtocolPolicy samlDiscoveryProtocolIsPassive samlOverrideIDPEntityID)];
our $oidcServiceParameters = [qw(oidcServiceMetaDataIssuer oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI oidcServiceMetaDataIntrospectionURI oidcServiceMetaDataEndSessionURI oidcServiceMetaDataCheckSessionURI oidcServiceMetaDataFrontChannelURI oidcServiceMetaDataBackChannelURI oidcServiceMetaDataAuthnContext oidcServicePrivateKeySig oidcServicePublicKeySig oidcServiceKeyIdSig oidcServiceAllowDynamicRegistration oidcServiceAllowAuthorizationCodeFlow oidcServiceAllowImplicitFlow oidcServiceAllowHybridFlow oidcStorage oidcStorageOptions)];
our $oidcServiceParameters = [qw(oidcServiceMetaDataIssuer oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI oidcServiceMetaDataIntrospectionURI oidcServiceMetaDataEndSessionURI oidcServiceMetaDataCheckSessionURI oidcServiceMetaDataFrontChannelURI oidcServiceMetaDataBackChannelURI oidcServiceMetaDataAuthnContext oidcServicePrivateKeySig oidcServicePublicKeySig oidcServiceKeyIdSig oidcServiceAllowDynamicRegistration oidcServiceAllowAuthorizationCodeFlow oidcServiceAllowImplicitFlow oidcServiceAllowHybridFlow oidcServiceAllowOffline oidcServiceAuthorizationCodeExpiration oidcServiceAccessTokenExpiration oidcServiceIDTokenExpiration oidcServiceRefreshTokenExpiration oidcStorage oidcStorageOptions)];
1;

View File

@ -1979,8 +1979,13 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'type' => 'subContainer'
},
'oidcRPMetaDataOptionsAccessTokenExpiration' => {
'default' => 3600,
'type' => 'int'
'type' => 'int'
},
'oidcRPMetaDataOptionsAllowOffline' => {
'type' => 'bool'
},
'oidcRPMetaDataOptionsAuthorizationCodeExpiration' => {
'type' => 'int'
},
'oidcRPMetaDataOptionsBypassConsent' => {
'default' => 0,
@ -2003,8 +2008,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'type' => 'text'
},
'oidcRPMetaDataOptionsIDTokenExpiration' => {
'default' => 3600,
'type' => 'int'
'type' => 'int'
},
'oidcRPMetaDataOptionsIDTokenSignAlg' => {
'default' => 'HS512',
@ -2069,6 +2073,9 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'oidcRPMetaDataOptionsRedirectUris' => {
'type' => 'text'
},
'oidcRPMetaDataOptionsRefreshTokenExpiration' => {
'type' => 'int'
},
'oidcRPMetaDataOptionsRequirePKCE' => {
'default' => 0,
'type' => 'bool'
@ -2086,6 +2093,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'default' => 600,
'type' => 'int'
},
'oidcServiceAccessTokenExpiration' => {
'default' => 3600,
'type' => 'int'
},
'oidcServiceAllowAuthorizationCodeFlow' => {
'default' => 1,
'type' => 'bool'
@ -2102,6 +2113,18 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'default' => 0,
'type' => 'bool'
},
'oidcServiceAllowOffline' => {
'default' => 0,
'type' => 'bool'
},
'oidcServiceAuthorizationCodeExpiration' => {
'default' => 60,
'type' => 'int'
},
'oidcServiceIDTokenExpiration' => {
'default' => 3600,
'type' => 'int'
},
'oidcServiceKeyIdSig' => {
'type' => 'text'
},
@ -2165,6 +2188,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'oidcServicePublicKeySig' => {
'type' => 'RSAPublicKey'
},
'oidcServiceRefreshTokenExpiration' => {
'default' => 2592000,
'type' => 'int'
},
'oidcStorage' => {
'type' => 'PerlModule'
},

View File

@ -3619,6 +3619,31 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
default => 0,
documentation => 'OpenID Connect allow hybrid flow',
},
oidcServiceAllowOffline => {
type => 'bool',
default => 0,
documentation => 'OpenID Connect allow offline access',
},
oidcServiceAuthorizationCodeExpiration => {
type => 'int',
default => 60,
documentation => 'OpenID Connect global code TTL',
},
oidcServiceAccessTokenExpiration => {
type => 'int',
default => 3600,
documentation => 'OpenID Connect global access token TTL',
},
oidcServiceIDTokenExpiration => {
type => 'int',
default => 3600,
documentation => 'OpenID Connect global ID token TTL',
},
oidcServiceRefreshTokenExpiration => {
type => 'int',
default => 2592000,
documentation => 'OpenID Connect global refresh token TTL',
},
oidcStorage => {
type => 'PerlModule',
documentation => 'Apache::Session module to store OIDC user data',
@ -3719,11 +3744,11 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
],
default => 'HS512',
},
oidcRPMetaDataOptionsIDTokenExpiration =>
{ type => 'int', default => 3600 },
oidcRPMetaDataOptionsAccessTokenExpiration =>
{ type => 'int', default => 3600 },
oidcRPMetaDataOptionsRedirectUris => { type => 'text', },
oidcRPMetaDataOptionsIDTokenExpiration => { type => 'int' },
oidcRPMetaDataOptionsAccessTokenExpiration => { type => 'int' },
oidcRPMetaDataOptionsAuthorizationCodeExpiration => { type => 'int' },
oidcRPMetaDataOptionsRefreshTokenExpiration => { type => 'int' },
oidcRPMetaDataOptionsRedirectUris => { type => 'text', },
oidcRPMetaDataOptionsExtraClaims =>
{ type => 'keyTextContainer', default => {} },
oidcRPMetaDataOptionsBypassConsent => {
@ -3760,6 +3785,10 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
default => 0,
documentation => 'Require PKCE',
},
oidcRPMetaDataOptionsAllowOffline => {
type => 'bool',
documentation => 'Allow offline access',
},
oidcRPMetaDataOptionsRule => {
type => 'text',
test => sub { return perlExpr(@_) },

View File

@ -204,6 +204,9 @@ sub cTrees {
'oidcRPMetaDataOptionsIDTokenSignAlg',
'oidcRPMetaDataOptionsIDTokenExpiration',
'oidcRPMetaDataOptionsAccessTokenExpiration',
'oidcRPMetaDataOptionsAuthorizationCodeExpiration',
'oidcRPMetaDataOptionsAllowOffline',
'oidcRPMetaDataOptionsRefreshTokenExpiration',
'oidcRPMetaDataOptionsRedirectUris',
'oidcRPMetaDataOptionsBypassConsent',
{

View File

@ -1166,6 +1166,11 @@ sub tree {
'oidcServiceAllowAuthorizationCodeFlow',
'oidcServiceAllowImplicitFlow',
'oidcServiceAllowHybridFlow',
'oidcServiceAllowOffline',
'oidcServiceAuthorizationCodeExpiration',
'oidcServiceAccessTokenExpiration',
'oidcServiceIDTokenExpiration',
'oidcServiceRefreshTokenExpiration',
],
},
{

View File

@ -473,19 +473,35 @@ function templates(tpl,key) {
"type" : "select"
},
{
"default" : 3600,
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsIDTokenExpiration",
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsIDTokenExpiration",
"title" : "oidcRPMetaDataOptionsIDTokenExpiration",
"type" : "int"
},
{
"default" : 3600,
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAccessTokenExpiration",
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAccessTokenExpiration",
"title" : "oidcRPMetaDataOptionsAccessTokenExpiration",
"type" : "int"
},
{
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAuthorizationCodeExpiration",
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAuthorizationCodeExpiration",
"title" : "oidcRPMetaDataOptionsAuthorizationCodeExpiration",
"type" : "int"
},
{
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAllowOffline",
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAllowOffline",
"title" : "oidcRPMetaDataOptionsAllowOffline",
"type" : "bool"
},
{
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRefreshTokenExpiration",
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRefreshTokenExpiration",
"title" : "oidcRPMetaDataOptionsRefreshTokenExpiration",
"type" : "int"
},
{
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRedirectUris",
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRedirectUris",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -528,6 +528,7 @@
"oidcOPMetaDataNode":" أوبين أيدي كونيكت بروفيدر",
"oidcOPMetaDataOptions":"الخيارات",
"oidcRPMetaDataOptionsAuthentication":"إثبات الهوية",
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
"oidcOPMetaDataOptionsCheckJWTSignature":"توقيع",
"oidcOPMetaDataOptionsClientID":"معرف العميل",
"oidcOPMetaDataOptionsClientSecret":"سرالعميل",
@ -557,6 +558,7 @@
"oidcRPMetaDataNode":"الأطراف المعتمد لي أوبين أيدي كونيكت",
"oidcRPMetaDataOptions":"الخيارات",
"oidcRPMetaDataOptionsAccessTokenExpiration":"انتهاء صلاحية التوكن",
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
"oidcRPMetaDataOptionsBypassConsent":"تخطى الموافقة ",
"oidcRPMetaDataOptionsClientID":"معرف العميل",
"oidcRPMetaDataOptionsClientSecret":"سرالعميل",
@ -565,6 +567,7 @@
"oidcRPMetaDataOptionsIcon":"شعار",
"oidcRPMetaDataOptionsIDTokenExpiration":" انتهاء صلاحية تعريف التوكن",
"oidcRPMetaDataOptionsIDTokenSignAlg":"خوارزمية توقيع آي دي التوكن",
"oidcRPMetaDataOptionsRefreshTokenExpiration":"Refresh Token expiration",
"oidcRPMetaDataOptionsUserIDAttr":"خاصّيّة المستخدم",
"oidcRPName":"اسم أوبين أيدي كونيكت RP",
"oidcRPStateTimeout":"حالة مهلة الجلسة",
@ -584,6 +587,10 @@
"oidcServicePrivateKeySig":"توقيع على المفتاح الخاص",
"oidcServicePublicKeySig":"توقيع على المفتاح العمومي",
"oidcServiceKeyIdSig":"توقيع على هوية المفتاح ",
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
"oidcServiceAccessTokenExpiration":"ﺎﻨﺘﻫﺍﺀ ﺹﻼﺤﻳﺓ ﺎﻠﺗﻮﻜﻧ",
"oidcServiceIDTokenExpiration":" ﺎﻨﺘﻫﺍﺀ ﺹﻼﺤﻳﺓ ﺖﻋﺮﻴﻓ ﺎﻠﺗﻮﻜﻧ",
"oidcServiceRefreshTokenExpiration":"Refresh Token expiration",
"oidcStorage":"اسم وحدة الجلسات",
"oidcStorageOptions":"خيارات وحدة الجلسات",
"oidcOPMetaDataNodes":" أوبين أيدي كونيكت بروفيدر",
@ -605,6 +612,7 @@
"oidcServiceAllowAuthorizationCodeFlow":"ترخيص كود التدفق",
"oidcServiceAllowImplicitFlow":"التدفق الضمني",
"oidcServiceAllowHybridFlow":"تدفق هجين",
"oidcServiceAllowOffline":"Allow offline access",
"ok":"حسنا",
"oldNotifFormat":"استخدام صيغة xml القديمة",
"openIdAttr":"تسجيل الدخول في أوبين أيدي",
@ -1066,4 +1074,4 @@
"samlRelayStateTimeout":"تناوب حالة مهلة الجلسة ",
"samlUseQueryStringSpecific":"استخدام أسلوب query_string المعين",
"samlOverrideIDPEntityID":"Override Entity ID when acting as IDP"
}
}

View File

@ -528,6 +528,7 @@
"oidcOPMetaDataNode":"OpenID Connect Providers",
"oidcOPMetaDataOptions":"Optionen",
"oidcRPMetaDataOptionsAuthentication":"Authentication",
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
"oidcOPMetaDataOptionsClientID":"Client ID",
"oidcOPMetaDataOptionsClientSecret":"Client secret",
@ -556,7 +557,8 @@
"oidcRPMetaDataExportedVars":"Exported attributes",
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
"oidcRPMetaDataOptions":"Options",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access token expiration",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access Token expiration",
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
"oidcRPMetaDataOptionsClientID":"Client ID",
"oidcRPMetaDataOptionsClientSecret":"Client secret",
@ -565,6 +567,7 @@
"oidcRPMetaDataOptionsIcon":"Logo",
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
"oidcRPMetaDataOptionsRefreshTokenExpiration":"Refresh Token expiration",
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
"oidcRPName":"OpenID Connect RP Name",
"oidcRPStateTimeout":"State session timeout",
@ -584,6 +587,10 @@
"oidcServicePrivateKeySig":"Signing private key",
"oidcServicePublicKeySig":"Signing public key",
"oidcServiceKeyIdSig":"Signing key ID",
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
"oidcServiceAccessTokenExpiration":"Access Token expiration",
"oidcServiceIDTokenExpiration":"ID Token expiration",
"oidcServiceRefreshTokenExpiration":"Refresh Token expiration",
"oidcStorage":"Sessions module name",
"oidcStorageOptions":"Sessions module options",
"oidcOPMetaDataNodes":"OpenID Connect Providers",
@ -605,6 +612,7 @@
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
"oidcServiceAllowImplicitFlow":"Implicit Flow",
"oidcServiceAllowHybridFlow":"Hybrid Flow",
"oidcServiceAllowOffline":"Allow offline access",
"ok":"OK",
"oldNotifFormat":"Use old XML format",
"openIdAttr":"OpenID login",
@ -1066,4 +1074,4 @@
"samlRelayStateTimeout":"RelayState session timeout",
"samlUseQueryStringSpecific":"Use specific query_string method",
"samlOverrideIDPEntityID":"Override Entity ID when acting as IDP"
}
}

View File

@ -528,6 +528,7 @@
"oidcOPMetaDataNode":"OpenID Connect Providers",
"oidcOPMetaDataOptions":"Options",
"oidcRPMetaDataOptionsAuthentication":"Authentication",
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
"oidcOPMetaDataOptionsClientID":"Client ID",
"oidcOPMetaDataOptionsClientSecret":"Client secret",
@ -556,7 +557,8 @@
"oidcRPMetaDataExportedVars":"Exported attributes",
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
"oidcRPMetaDataOptions":"Options",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access token expiration",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access Token expiration",
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
"oidcRPMetaDataOptionsClientID":"Client ID",
"oidcRPMetaDataOptionsClientSecret":"Client secret",
@ -565,6 +567,7 @@
"oidcRPMetaDataOptionsIcon":"Logo",
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
"oidcRPMetaDataOptionsRefreshTokenExpiration":"Refresh Token expiration",
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
"oidcRPName":"OpenID Connect RP Name",
"oidcRPStateTimeout":"State session timeout",
@ -584,6 +587,10 @@
"oidcServicePrivateKeySig":"Signing private key",
"oidcServicePublicKeySig":"Signing public key",
"oidcServiceKeyIdSig":"Signing key ID",
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
"oidcServiceAccessTokenExpiration":"Access Token expiration",
"oidcServiceIDTokenExpiration":"ID Token expiration",
"oidcServiceRefreshTokenExpiration":"Refresh Token expiration",
"oidcStorage":"Sessions module name",
"oidcStorageOptions":"Sessions module options",
"oidcOPMetaDataNodes":"OpenID Connect Providers",
@ -605,6 +612,7 @@
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
"oidcServiceAllowImplicitFlow":"Implicit Flow",
"oidcServiceAllowHybridFlow":"Hybrid Flow",
"oidcServiceAllowOffline":"Allow offline access",
"ok":"OK",
"oldNotifFormat":"Use old XML format",
"openIdAttr":"OpenID login",

View File

@ -528,6 +528,7 @@
"oidcOPMetaDataNode":"Fournisseurs OpenID Connect",
"oidcOPMetaDataOptions":"Options",
"oidcRPMetaDataOptionsAuthentication":"Authentification",
"oidcRPMetaDataOptionsAllowOffline":"Autoriser l'accès hors ligne",
"oidcOPMetaDataOptionsCheckJWTSignature":"Vérifier la signature des jetons",
"oidcOPMetaDataOptionsClientID":"Identifiant",
"oidcOPMetaDataOptionsClientSecret":"Mot de passe",
@ -557,6 +558,7 @@
"oidcRPMetaDataNode":"Clients OpenID Connect",
"oidcRPMetaDataOptions":"Options",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Expiration des jetons d'accès",
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Expiration des codes d'autorisation",
"oidcRPMetaDataOptionsBypassConsent":"Contourner le consentement",
"oidcRPMetaDataOptionsClientID":"Identifiant",
"oidcRPMetaDataOptionsClientSecret":"Mot de passe",
@ -565,6 +567,7 @@
"oidcRPMetaDataOptionsIcon":"Logo",
"oidcRPMetaDataOptionsIDTokenExpiration":"Expiration des jetons d'identité",
"oidcRPMetaDataOptionsIDTokenSignAlg":"Algorithme de signature des jetons d'identité",
"oidcRPMetaDataOptionsRefreshTokenExpiration":"Expiration des jetons de renouvellement",
"oidcRPMetaDataOptionsUserIDAttr":"Attribut de l'utilisateur",
"oidcRPName":"Nom du client OpenID Connect",
"oidcRPStateTimeout":"Durée d'une session state",
@ -584,6 +587,10 @@
"oidcServicePrivateKeySig":"Clef privée de signature",
"oidcServicePublicKeySig":"Clef publique de signature",
"oidcServiceKeyIdSig":"Identifiant de clef de signature",
"oidcServiceAuthorizationCodeExpiration":"Expiration des codes d'autorisation",
"oidcServiceAccessTokenExpiration":"Expiration des jetons d'accès",
"oidcServiceIDTokenExpiration":"Expiration des jetons d'identité",
"oidcServiceRefreshTokenExpiration":"Expiration des jetons de renouvellement",
"oidcStorage":"Nom du module des sessions",
"oidcStorageOptions":"Options du module des sessions",
"oidcOPMetaDataNodes":"Fournisseurs OpenID Connect",
@ -605,6 +612,7 @@
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
"oidcServiceAllowImplicitFlow":"Implicit Flow",
"oidcServiceAllowHybridFlow":"Hybrid Flow",
"oidcServiceAllowOffline":"Autoriser l'accès hors ligne",
"ok":"OK",
"oldNotifFormat":"Utiliser l'ancien format XML",
"openIdAttr":"Identifiant OpenID",

View File

@ -528,6 +528,7 @@
"oidcOPMetaDataNode":"Provider di OpenID Connect",
"oidcOPMetaDataOptions":"Opzioni",
"oidcRPMetaDataOptionsAuthentication":"Autenticazione",
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
"oidcOPMetaDataOptionsCheckJWTSignature":"Controllare la firma JWT",
"oidcOPMetaDataOptionsClientID":"ID Client",
"oidcOPMetaDataOptionsClientSecret":"Segreto Client",
@ -557,6 +558,7 @@
"oidcRPMetaDataNode":"Parti basate su OpenID Connect",
"oidcRPMetaDataOptions":"Opzioni",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Scadenza accesso token",
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Scadenza Authorization Code",
"oidcRPMetaDataOptionsBypassConsent":"Consenso di bypass",
"oidcRPMetaDataOptionsClientID":"ID Client",
"oidcRPMetaDataOptionsClientSecret":"Segreto Client",
@ -565,6 +567,7 @@
"oidcRPMetaDataOptionsIcon":"Logo",
"oidcRPMetaDataOptionsIDTokenExpiration":"Scadenza ID Token",
"oidcRPMetaDataOptionsIDTokenSignAlg":"Algoritmo di firma di identificazione di Token",
"oidcRPMetaDataOptionsRefreshTokenExpiration":"Scadenza Refresh Token",
"oidcRPMetaDataOptionsUserIDAttr":"Attributo utente",
"oidcRPName":"Nome di OpenID Connect RP",
"oidcRPStateTimeout":"Durata della sessione stato",
@ -584,6 +587,10 @@
"oidcServicePrivateKeySig":"Firma della chiave privata",
"oidcServicePublicKeySig":"Firma della chiave pubblica",
"oidcServiceKeyIdSig":"ID del codice di accesso",
"oidcServiceAuthorizationCodeExpiration":"Scadenza Authorization Code",
"oidcServiceAccessTokenExpiration":"Scadenza accesso token",
"oidcServiceIDTokenExpiration":"Scadenza ID Token",
"oidcServiceRefreshTokenExpiration":"Scadenza Refresh Token",
"oidcStorage":"Nome del modulo Sessioni",
"oidcStorageOptions":"Opzioni del modulo Sessioni",
"oidcOPMetaDataNodes":"Provider di OpenID Connect",
@ -605,6 +612,7 @@
"oidcServiceAllowAuthorizationCodeFlow":"Flusso del codice di autorizzazione",
"oidcServiceAllowImplicitFlow":"Flusso implicito",
"oidcServiceAllowHybridFlow":"Flusso ibrido",
"oidcServiceAllowOffline":"Allow offline access",
"ok":"OK",
"oldNotifFormat":"Utilizza il vecchio formato XML",
"openIdAttr":"Login OpenID",
@ -1066,4 +1074,4 @@
"samlRelayStateTimeout":"Timeout di sessione di RelayState",
"samlUseQueryStringSpecific":"Utilizza il metodo specifico query_string",
"samlOverrideIDPEntityID":"Sostituisci l'ID entità quando agisce come IDP"
}
}

View File

@ -528,6 +528,7 @@
"oidcOPMetaDataNode":"Nhà cung cấp Kết nối OpenID",
"oidcOPMetaDataOptions":"Tùy chọn",
"oidcRPMetaDataOptionsAuthentication":"Xác thực",
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
"oidcOPMetaDataOptionsCheckJWTSignature":"Kiểm tra chữ ký JWT",
"oidcOPMetaDataOptionsClientID":"Client ID",
"oidcOPMetaDataOptionsClientSecret":"Trình khách bí mật",
@ -557,6 +558,7 @@
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
"oidcRPMetaDataOptions":"Tùy chọn",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Hết hạn truy cập Token",
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code hết hạn",
"oidcRPMetaDataOptionsBypassConsent":"Bỏ qua sự đồng ý",
"oidcRPMetaDataOptionsClientID":"Client ID",
"oidcRPMetaDataOptionsClientSecret":"Trình khách bí mật",
@ -565,6 +567,7 @@
"oidcRPMetaDataOptionsIcon":"Logo",
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token hết hạn",
"oidcRPMetaDataOptionsIDTokenSignAlg":"Thuật toán chữ ký ID Token",
"oidcRPMetaDataOptionsRefreshTokenExpiration":"Refresh Token hết hạn",
"oidcRPMetaDataOptionsUserIDAttr":"thuộc tính người dùng",
"oidcRPName":"OpenID Connect RP Name",
"oidcRPStateTimeout":"Thời gian chờ của trạng thái phiên làm việc",
@ -584,6 +587,10 @@
"oidcServicePrivateKeySig":"Ký khóa cá nhân",
"oidcServicePublicKeySig":"Ký khóa công khai",
"oidcServiceKeyIdSig":"Khóa ID chính",
"oidcServiceAuthorizationCodeExpiration":"Authorization Code hết hạn",
"oidcServiceAccessTokenExpiration":"Hết hạn truy cập Token",
"oidcServiceIDTokenExpiration":"ID Token hết hạn",
"oidcServiceRefreshTokenExpiration":"Refresh Token hết hạn",
"oidcStorage":"Tên mô-đun phiên",
"oidcStorageOptions":"Tùy chọn mô-đun phiên",
"oidcOPMetaDataNodes":"Nhà cung cấp Kết nối OpenID",
@ -605,6 +612,7 @@
"oidcServiceAllowAuthorizationCodeFlow":"Dòng mã ủy quyền",
"oidcServiceAllowImplicitFlow":"Dòng chảy ngầm",
"oidcServiceAllowHybridFlow":"Dòng chảy hỗn hợp",
"oidcServiceAllowOffline":"Allow offline access",
"ok":"OK",
"oldNotifFormat":"Sử dụng định dạng XML cũ",
"openIdAttr":"Đăng nhập OpenID",
@ -1066,4 +1074,4 @@
"samlRelayStateTimeout":"Thời gian hết hạn phiên RelayState ",
"samlUseQueryStringSpecific":"Sử dụng phương pháp query_string cụ thể",
"samlOverrideIDPEntityID":"Override Entity ID when acting as IDP"
}
}

View File

@ -528,6 +528,7 @@
"oidcOPMetaDataNode":"OpenID Connect Providers",
"oidcOPMetaDataOptions":"Options",
"oidcRPMetaDataOptionsAuthentication":"Authentication",
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
"oidcOPMetaDataOptionsClientID":"Client ID",
"oidcOPMetaDataOptionsClientSecret":"Client secret",
@ -556,7 +557,8 @@
"oidcRPMetaDataExportedVars":"Exported attributes",
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
"oidcRPMetaDataOptions":"Options",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access token expiration",
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access Token expiration",
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
"oidcRPMetaDataOptionsClientID":"Client ID",
"oidcRPMetaDataOptionsClientSecret":"Client secret",
@ -565,6 +567,7 @@
"oidcRPMetaDataOptionsIcon":"Logo",
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
"oidcRPMetaDataOptionsRefreshTokenExpiration":"Refresh Token expiration",
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
"oidcRPName":"OpenID Connect RP Name",
"oidcRPStateTimeout":"State session timeout",
@ -584,6 +587,10 @@
"oidcServicePrivateKeySig":"Signing private key",
"oidcServicePublicKeySig":"Signing public key",
"oidcServiceKeyIdSig":"Signing key ID",
"oidcServiceAuthorizationCodeExpiration":"Authorization code expiration",
"oidcServiceAccessTokenExpiration":"Access Token expiration",
"oidcServiceIDTokenExpiration":"ID Token expiration",
"oidcServiceRefreshTokenExpiration":"Refresh Token expiration",
"oidcStorage":"Sessions module name",
"oidcStorageOptions":"Sessions module options",
"oidcOPMetaDataNodes":"OpenID Connect Providers",
@ -605,6 +612,7 @@
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
"oidcServiceAllowImplicitFlow":"Implicit Flow",
"oidcServiceAllowHybridFlow":"Hybrid Flow",
"oidcServiceAllowOffline":"Allow offline access",
"ok":"OK",
"oldNotifFormat":"Use old XML format",
"openIdAttr":"OpenID login",
@ -1066,4 +1074,4 @@
"samlRelayStateTimeout":"RelayState session timeout",
"samlUseQueryStringSpecific":"Use specific query_string method",
"samlOverrideIDPEntityID":"Override Entity ID when acting as IDP"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,6 +6,7 @@ use Mouse;
use Lemonldap::NG::Common::FormEncode;
use Lemonldap::NG::Portal::Main::Constants qw(
PE_BADURL
PE_BADCREDENTIALS
PE_CONFIRM
PE_ERROR
PE_LOGOUT_OK
@ -547,11 +548,12 @@ sub run {
}
my $scope_messages = {
openid => 'yourIdentity',
profile => 'yourProfile',
email => 'yourEmail',
address => 'yourAddress',
phone => 'yourPhone',
openid => 'yourIdentity',
profile => 'yourProfile',
email => 'yourEmail',
address => 'yourAddress',
phone => 'yourPhone',
offline_access => 'yourOffline',
};
my @list;
foreach my $requested_scope (
@ -609,6 +611,48 @@ sub run {
);
}
# WIP: Offline access
my $offline = 0;
if ( $oidc_request->{'scope'} =~ /\boffline_access\b/ ) {
$offline = 1;
# MUST ensure that the prompt parameter contains consent unless
# other conditions for processing the request permitting offline
# access to the requested resources are in place; unless one or
# both of these conditions are fulfilled, then it MUST ignore
# the offline_access request,
unless ( $bypassConsent
or ( $prompt and $prompt =~ /\bconsent\b/ ) )
{
$self->logger->warn(
"Offline access ignored, prompt parameter must contain \"consent\"");
$offline = 0;
}
# MUST ignore the offline_access request unless the Client is
# using a response_type value that would result in an
# Authorization Code being returned,
if ( $response_type !~ /\bcode\b/ ) {
$self->logger->warn(
"Offline access incompatible with response type $response_type");
$offline = 0;
}
# Ignore offline_access request if not authorized by the RP
unless ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAllowOffline}
|| $self->conf->{oidcServiceAllowOffline} )
{
$self->logger->warn(
"Offline access not authorized for RP $rp");
$offline = 0;
}
# Strip offline_access from scopes from now on
$oidc_request->{'scope'} = join " ", grep !/^offline_access$/,
split /\s+/, $oidc_request->{'scope'};
}
# Authorization Code Flow
if ( $flow eq "authorizationcode" ) {
@ -616,14 +660,15 @@ sub run {
my $codeSession = $self->newAuthorizationCode(
$rp,
{
code_challenge => $oidc_request->{'code_challenge'},
code_challenge_method =>
$oidc_request->{'code_challenge_method'},
nonce => $oidc_request->{'nonce'},
offline => $offline,
redirect_uri => $oidc_request->{'redirect_uri'},
scope => $oidc_request->{'scope'},
client_id => $client_id,
user_session_id => $req->id,
nonce => $oidc_request->{'nonce'},
code_challenge => $oidc_request->{'code_challenge'},
code_challenge_method =>
$oidc_request->{'code_challenge_method'},
}
);
@ -687,8 +732,10 @@ sub run {
}
# ID token payload
my $id_token_exp = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenExpiration};
my $id_token_exp =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenExpiration}
|| $self->conf->{oidcServiceIDTokenExpiration};
$id_token_exp += time;
my $authenticationLevel =
@ -733,7 +780,8 @@ sub run {
# No access_token
# Claims must be set in id_token
my $claims =
$self->buildUserInfoResponse( $oidc_request->{'scope'},
$self->buildUserInfoResponseFromId(
$oidc_request->{'scope'},
$rp, $req->id );
foreach ( keys %$claims ) {
@ -749,8 +797,10 @@ sub run {
$self->logger->debug("Generated id token: $id_token");
# Send token response
my $expires_in = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAccessTokenExpiration};
my $expires_in =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|| $self->conf->{oidcServiceAccessTokenExpiration};
# Build Response
my $response_url = $self->buildImplicitAuthnResponse(
@ -783,11 +833,12 @@ sub run {
my $codeSession = $self->newAuthorizationCode(
$rp,
{
nonce => $oidc_request->{'nonce'},
offline => $offline,
redirect_uri => $oidc_request->{'redirect_uri'},
client_id => $client_id,
scope => $oidc_request->{'scope'},
user_session_id => $req->id,
nonce => $oidc_request->{'nonce'},
}
);
@ -836,11 +887,13 @@ sub run {
# ID token payload
my $id_token_exp =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenExpiration};
->{oidcRPMetaDataOptionsIDTokenExpiration}
|| $self->conf->{oidcServiceIDTokenExpiration};
$id_token_exp += time;
my $id_token_acr =
"loa-" . $req->{sessionInfo}->{authenticationLevel};
"loa-"
. ( $req->{sessionInfo}->{authenticationLevel} || 0 );
my $user_id_attribute =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
@ -870,7 +923,7 @@ sub run {
# No access_token
# Claims must be set in id_token
my $claims = $self->buildUserInfoResponse(
my $claims = $self->buildUserInfoResponseFromId(
$oidc_request->{'scope'},
$rp, $req->id );
@ -887,8 +940,10 @@ sub run {
$self->logger->debug("Generated id token: $id_token");
}
my $expires_in = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAccessTokenExpiration};
my $expires_in =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|| $self->conf->{oidcServiceAccessTokenExpiration};
# Build Response
my $response_url = $self->buildHybridAuthnResponse(
@ -1013,152 +1068,340 @@ sub token {
my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID};
# Get code session
my $code = $req->param('code');
my $grant_type = $req->param('grant_type');
unless ($code) {
$self->logger->error("No code found on token endpoint");
return $self->p->sendError( $req, 'invalid_request', 400 );
}
# Autorization Code grant
if ( $grant_type eq 'authorization_code' ) {
my $code = $req->param('code');
$self->logger->debug("OpenID Connect Code: $code");
unless ($code) {
$self->logger->error("No code found on token endpoint");
return $self->p->sendError( $req, 'invalid_request', 400 );
}
my $codeSession = $self->getAuthorizationCode($code);
my $codeSession = $self->getAuthorizationCode($code);
unless ($codeSession) {
$self->logger->error("Unable to find OIDC session $code");
return $self->p->sendError( $req, 'invalid_request', 400 );
}
unless ($codeSession) {
$self->logger->error("Unable to find OIDC session $code");
return $self->p->sendError( $req, 'invalid_request', 400 );
}
# Check PKCE
if ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsRequirePKCE} )
{
unless (
$self->validatePKCEChallenge(
$req->param('code_verifier'),
$codeSession->data->{'code_challenge'},
$codeSession->data->{'code_challenge_method'}
)
)
$codeSession->remove();
# Check PKCE
if ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsRequirePKCE} )
{
unless (
$self->validatePKCEChallenge(
$req->param('code_verifier'),
$codeSession->data->{'code_challenge'},
$codeSession->data->{'code_challenge_method'}
)
)
{
return $self->p->sendError( $req, 'invalid_grant', 400 );
}
}
# Check we have the same client_id value
unless ( $client_id eq $codeSession->data->{client_id} ) {
$self->userLogger->error( "Provided client_id does not match "
. $codeSession->data->{client_id} );
return $self->p->sendError( $req, 'invalid_grant', 400 );
}
}
# Check we have the same client_id value
unless ( $client_id eq $codeSession->data->{client_id} ) {
$self->userLogger->error( "Provided client_id does not match "
. $codeSession->data->{client_id} );
return $self->p->sendError( $req, 'invalid_grant', 400 );
}
# Check we have the same redirect_uri value
unless ( $req->param("redirect_uri") eq $codeSession->data->{redirect_uri} )
{
$self->userLogger->error( "Provided redirect_uri does not match "
. $codeSession->data->{redirect_uri} );
return $self->p->sendError( $req, 'invalid_request', 400 );
}
# Get user identifier
my $apacheSession =
$self->p->getApacheSession( $codeSession->data->{user_session_id},
noInfo => 1 );
unless ($apacheSession) {
$self->userLogger->error(
"Unable to find user session linked to OIDC session $code");
$codeSession->remove();
return $self->p->sendError( $req, 'invalid_request', 400 );
}
my $user_id_attribute =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsUserIDAttr}
|| $self->conf->{whatToTrace};
my $user_id = $apacheSession->data->{$user_id_attribute};
$self->logger->debug("Found corresponding user: $user_id");
# Generate access_token
my $accessTokenSession = $self->newAccessToken(
$rp,
# Check we have the same redirect_uri value
unless (
$req->param("redirect_uri") eq $codeSession->data->{redirect_uri} )
{
scope => $codeSession->data->{scope},
rp => $rp,
user_session_id => $apacheSession->id,
$self->userLogger->error( "Provided redirect_uri does not match "
. $codeSession->data->{redirect_uri} );
return $self->p->sendError( $req, 'invalid_grant', 400 );
}
);
unless ($accessTokenSession) {
# Get user identifier
my $apacheSession =
$self->p->getApacheSession( $codeSession->data->{user_session_id},
noInfo => 1 );
unless ($apacheSession) {
$self->userLogger->error("Unable to find user session");
return $self->p->sendError( $req, 'invalid_grant', 400 );
}
my $user_id_attribute =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsUserIDAttr}
|| $self->conf->{whatToTrace};
my $user_id = $apacheSession->data->{$user_id_attribute};
$self->logger->debug("Found corresponding user: $user_id");
# Generate access_token
my $accessTokenSession = $self->newAccessToken(
$rp,
{
scope => $codeSession->data->{scope},
rp => $rp,
user_session_id => $apacheSession->id,
}
);
unless ($accessTokenSession) {
$self->userLogger->error(
"Unable to create OIDC session for access_token");
#FIXME: should be an error 500
return $self->p->sendError( $req, 'invalid_request', 400 );
}
my $access_token = $accessTokenSession->id;
$self->logger->debug("Generated access token: $access_token");
# Generate refresh_token
my $refresh_token = undef;
if ( $codeSession->{data}->{offline} ) {
my $refreshTokenSession = $self->newRefreshToken(
$rp,
{
redirect_uri => $codeSession->data->{redirect_uri},
scope => $codeSession->data->{scope},
client_id => $client_id,
user_session_id => $apacheSession->id,
_session_uid => $apacheSession->data->{_user},
}
);
unless ($refreshTokenSession) {
$self->userLogger->error(
"Unable to create OIDC session for refresh_token");
return $self->p->sendError( $req, 'invalid_request', 400 );
}
$refresh_token = $refreshTokenSession->id;
$self->logger->debug("Generated refresh token: $refresh_token");
}
# Compute hash to store in at_hash
my $alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenSignAlg};
my ($hash_level) = ( $alg =~ /(?:\w{2})(\d{3})/ );
my $at_hash = $self->createHash( $access_token, $hash_level )
if $hash_level;
# ID token payload
my $id_token_exp =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenExpiration}
|| $self->conf->{oidcServiceIDTokenExpiration};
$id_token_exp += time;
my $id_token_acr = "loa-" . $apacheSession->data->{authenticationLevel};
my $id_token_payload_hash = {
iss => $self->conf->{oidcServiceMetaDataIssuer}, # Issuer Identifier
sub => $user_id, # Subject Identifier
aud => [$client_id], # Audience
exp => $id_token_exp, # expiration
iat => time, # Issued time
auth_time => $apacheSession->data->{_lastAuthnUTime}
, # Authentication time
acr => $id_token_acr, # Authentication Context Class Reference
azp => $client_id, # Authorized party
# TODO amr
};
my $nonce = $codeSession->data->{nonce};
$id_token_payload_hash->{nonce} = $nonce if defined $nonce;
$id_token_payload_hash->{'at_hash'} = $at_hash if $at_hash;
# Create ID Token
my $id_token = $self->createIDToken( $id_token_payload_hash, $rp );
$self->logger->debug("Generated id token: $id_token");
# Send token response
my $expires_in =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|| $self->conf->{oidcServiceAccessTokenExpiration};
my $token_response = {
access_token => $access_token,
token_type => 'Bearer',
expires_in => $expires_in,
id_token => $id_token,
( $refresh_token ? ( refresh_token => $refresh_token ) : () ),
};
my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
unless ( $cRP =~ /\b$rp\b/ ) {
$self->p->updateSession( $req, { _oidcConnectedRP => "$rp,$cRP" },
$apacheSession->id );
}
$self->logger->debug("Send token response");
return $self->p->sendJSONresponse( $req, $token_response );
}
# Refresh token
elsif ( $grant_type eq 'refresh_token' ) {
my $refresh_token = $req->param('refresh_token');
unless ($refresh_token) {
$self->logger->error("Missing refresh_token parameter");
return $self->p->sendError( $req, 'invalid_request', 400 );
}
$self->logger->debug("OpenID Refresh Token: $refresh_token");
my $refreshSession = $self->getRefreshToken($refresh_token);
unless ($refreshSession) {
$self->logger->error("Unable to find OIDC session $refresh_token");
return $self->p->sendError( $req, 'invalid_request', 400 );
}
# Check we have the same client_id value
unless ( $client_id eq $refreshSession->data->{client_id} ) {
$self->userLogger->error( "Provided client_id does not match "
. $refreshSession->data->{client_id} );
return $self->p->sendError( $req, 'invalid_grant', 400 );
}
# Lookup attributes and macros for user
$req->user( $refreshSession->data->{_session_uid} );
$req->steps( [
'getUser', @{ $self->p->betweenAuthAndData },
'setSessionInfo', 'setMacros',
'setGroups', 'setLocalGroups',
]
);
$req->{error} = $self->p->process($req);
if ( $req->error > 0 ) {
# PE_BADCREDENTIAL is returned by UserDB modules when the user was
# explicitely not found. And not in case of temporary failures
if ($req->error == PE_BADCREDENTIALS) {
$self->logger->error( "User: " . $req->user . " no longer exists, removing offline session");
$refreshSession->remove;
} else {
$self->logger->error( "Could not resolve user: " . $req->user );
}
return $self->p->sendError( $req, 'invalid_grant', 400 );
}
# Update refresh session
$self->updateRefreshToken( $refreshSession->id, $req->sessionInfo );
my $user_id_attribute =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsUserIDAttr}
|| $self->conf->{whatToTrace};
my $user_id = $req->sessionInfo->{$user_id_attribute};
$self->logger->debug("Found corresponding user: $user_id");
# Generate access_token
my $accessTokenSession = $self->newAccessToken(
$rp,
{
scope => $refreshSession->data->{scope},
rp => $rp,
offline_session_id => $refreshSession->id,
}
);
unless ($accessTokenSession) {
$self->userLogger->error(
"Unable to create OIDC session for access_token");
return $self->p->sendError( $req, 'Unable to create Access Token',
500 );
}
my $access_token = $accessTokenSession->id;
$self->logger->debug("Generated access token: $access_token");
# Compute hash to store in at_hash
my $alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenSignAlg};
my ($hash_level) = ( $alg =~ /(?:\w{2})(\d{3})/ );
my $at_hash = $self->createHash( $access_token, $hash_level )
if $hash_level;
# ID token payload
my $id_token_exp =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenExpiration}
|| $self->conf->{oidcServiceIDTokenExpiration};
$id_token_exp += time;
# TODO authentication level specific to refresh ?
my $id_token_acr = "loa-" . $req->sessionInfo->{authenticationLevel};
my $id_token_payload_hash = {
iss => $self->conf->{oidcServiceMetaDataIssuer}, # Issuer Identifier
sub => $user_id, # Subject Identifier
aud => [$client_id], # Audience
exp => $id_token_exp, # expiration
iat => time, # Issued time
# TODO: is this the right value when using refresh tokens??
auth_time => $req->sessionInfo->{_lastAuthnUTime}
, # Authentication time
acr => $id_token_acr, # Authentication Context Class Reference
azp => $client_id, # Authorized party
# TODO amr
};
my $nonce = $refreshSession->data->{nonce};
$id_token_payload_hash->{nonce} = $nonce if defined $nonce;
$id_token_payload_hash->{'at_hash'} = $at_hash if $at_hash;
# Create ID Token
my $id_token = $self->createIDToken( $id_token_payload_hash, $rp );
$self->logger->debug("Generated id token: $id_token");
# Send token response
my $expires_in =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|| $self->conf->{oidcServiceAccessTokenExpiration};
my $token_response = {
access_token => $access_token,
token_type => 'Bearer',
expires_in => $expires_in,
id_token => $id_token,
};
# TODO
#my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
#unless ( $cRP =~ /\b$rp\b/ ) {
# $self->p->updateSession( $req, { _oidcConnectedRP => "$rp,$cRP" },
# $apacheSession->id );
#}
$self->logger->debug("Send token response");
return $self->p->sendJSONresponse( $req, $token_response );
}
# Unknown or unspecified grant type
else {
$self->userLogger->error(
"Unable to create OIDC session for access_token");
$codeSession->remove();
return $self->p->sendError( $req, 'invalid_request', 400 );
$grant_type
? "Missing grant_type parameter"
: "Unknown grant type: $grant_type"
);
return $self->p->sendError( $req, 'unsupported_grant_type', 400 );
}
my $access_token = $accessTokenSession->id;
$self->logger->debug("Generated access token: $access_token");
# Compute hash to store in at_hash
my $alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenSignAlg};
my ($hash_level) = ( $alg =~ /(?:\w{2})(\d{3})/ );
my $at_hash = $self->createHash( $access_token, $hash_level )
if $hash_level;
# ID token payload
my $id_token_exp = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsIDTokenExpiration};
$id_token_exp += time;
my $id_token_acr = "loa-" . $apacheSession->data->{authenticationLevel};
my $id_token_payload_hash = {
iss => $self->iss,
sub => $user_id, # Subject Identifier
aud => [$client_id], # Audience
exp => $id_token_exp, # expiration
iat => time, # Issued time
auth_time => $apacheSession->data->{_lastAuthnUTime}
, # Authentication time
acr => $id_token_acr, # Authentication Context Class Reference
azp => $client_id, # Authorized party
# TODO amr
};
my $nonce = $codeSession->data->{nonce};
$id_token_payload_hash->{nonce} = $nonce if defined $nonce;
$id_token_payload_hash->{'at_hash'} = $at_hash if $at_hash;
# Create ID Token
my $id_token = $self->createIDToken( $id_token_payload_hash, $rp );
$self->logger->debug("Generated id token: $id_token");
# Send token response
my $expires_in = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAccessTokenExpiration};
my $token_response = {
access_token => $access_token,
token_type => 'Bearer',
expires_in => $expires_in,
id_token => $id_token,
};
my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
unless ( $cRP =~ /\b$rp\b/ ) {
$self->p->updateSession( $req, { _oidcConnectedRP => "$rp,$cRP" },
$apacheSession->id );
}
$self->logger->debug("Send token response");
$codeSession->remove();
return $self->p->sendJSONresponse( $req, $token_response );
}
# Handle userinfo endpoint
@ -1190,8 +1433,39 @@ sub userInfo {
my $rp = $accessTokenSession->data->{rp};
my $user_session_id = $accessTokenSession->data->{user_session_id};
my $session;
# If using a refreshed access token
if ($user_session_id) {
# Get user identifier
$session = $self->p->getApacheSession($user_session_id);
unless ($session) {
$self->logger->error("Unable to find user session");
return $self->returnBearerError( 'invalid_request',
'Invalid request', 401 );
}
}
else {
my $offline_session_id =
$accessTokenSession->data->{offline_session_id};
unless ($offline_session_id) {
return $self->returnBearerError( 'invalid_request',
'Invalid request', 401 );
}
$session = $self->getRefreshToken($offline_session_id);
unless ($session) {
$self->logger->error("Unable to find refresh session");
return $self->returnBearerError( 'invalid_request',
'Invalid request', 401 );
}
}
my $userinfo_response =
$self->buildUserInfoResponse( $scope, $rp, $user_session_id );
$self->buildUserInfoResponse( $scope, $rp, $session );
unless ($userinfo_response) {
return $self->returnBearerError( 'invalid_request', 'Invalid request',
401 );

View File

@ -637,8 +637,15 @@ sub decodeJSON {
sub newAuthorizationCode {
my ( $self, $rp, $info ) = @_;
return $self->getOpenIDConnectSession( undef, "authorization_code", undef,
$info );
return $self->getOpenIDConnectSession(
undef,
"authorization_code",
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAuthorizationCodeExpiration}
|| $self->conf->{oidcServiceAuthorizationCodeExpiration},
,
$info
);
}
# Get existing Authorization Code
@ -662,7 +669,8 @@ sub newAccessToken {
undef,
"access_token",
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsAccessTokenExpiration},
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|| $self->conf->{oidcServiceAccessTokenExpiration},
$info
);
}
@ -677,6 +685,67 @@ sub getAccessToken {
return $self->getOpenIDConnectSession( $id, "access_token" );
}
# Create a new Refresh Token
# @param info hashref of session info
# @return new Lemonldap::NG::Common::Session object
sub newRefreshToken {
my ( $self, $rp, $info ) = @_;
return $self->getOpenIDConnectSession(
undef,
"refresh_token",
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsRefreshTokenExpiration}
|| $self->conf->{oidcServiceRefreshTokenExpiration},
,
$info
);
}
# Get existing Refresh Token
# @param id
# @return new Lemonldap::NG::Common::Session object
sub getRefreshToken {
my ( $self, $id ) = @_;
return $self->getOpenIDConnectSession( $id, "refresh_token" );
}
sub updateRefreshToken {
my ( $self, $id, $infos ) = @_;
my %storage = (
storageModule => $self->conf->{oidcStorage},
storageModuleOptions => $self->conf->{oidcStorageOptions},
);
unless ( $storage{storageModule} ) {
%storage = (
storageModule => $self->conf->{globalStorage},
storageModuleOptions => $self->conf->{globalStorageOptions},
);
}
my $oidcSession = Lemonldap::NG::Common::Session->new( {
%storage,
cacheModule => $self->conf->{localSessionStorage},
cacheModuleOptions => $self->conf->{localSessionStorageOptions},
id => $id,
info => $infos,
}
);
if ( $oidcSession->error ) {
$self->userLogger->warn(
"OpenIDConnect session $id isn't yet available");
return undef;
}
return $oidcSession;
}
# Try to recover the OpenID Connect session corresponding to id and return session
# If id is set to undef, return a new session
# @return Lemonldap::NG::Common::Session object
@ -739,6 +808,15 @@ sub getOpenIDConnectSession {
. $type );
return undef;
}
# Make sure the token is still valid, we already compensated for
# different TTLs when storing _utime
if (
time > ( $oidcSession->{data}->{_utime} + $self->conf->{timeout} ) )
{
$self->logger->error("Session $id has expired");
return undef;
}
}
# Make sure the token is still valid, we already compensated for
@ -1221,22 +1299,28 @@ sub getAttributesListFromClaim {
# @param rp Internal Relying Party identifier
# @param user_session_id User session identifier
# @return hashref UserInfo data
sub buildUserInfoResponse {
sub buildUserInfoResponseFromId {
my ( $self, $scope, $rp, $user_session_id ) = @_;
my $session = $self->p->getApacheSession($user_session_id);
return undef unless ($session);
return buildUserInfoResponse( $self, $scope, $rp, $session );
}
# Return Hash of UserInfo data
# @param scope OIDC scope
# @param rp Internal Relying Party identifier
# @param session SSO or offline session
# @return hashref UserInfo data
sub buildUserInfoResponse {
my ( $self, $scope, $rp, $session ) = @_;
my $userinfo_response = {};
# Get user identifier
my $apacheSession = $self->p->getApacheSession($user_session_id);
unless ($apacheSession) {
$self->logger->error("Unable to find user session");
return undef;
}
my $user_id_attribute =
$self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsUserIDAttr}
|| $self->conf->{whatToTrace};
my $user_id = $apacheSession->data->{$user_id_attribute};
my $user_id = $session->data->{$user_id_attribute};
$self->logger->debug("Found corresponding user: $user_id");
@ -1252,7 +1336,7 @@ sub buildUserInfoResponse {
my $session_key =
$self->conf->{oidcRPMetaDataExportedVars}->{$rp}->{$attribute};
if ($session_key) {
my $session_value = $apacheSession->data->{$session_key};
my $session_value = $session->data->{$session_key};
# Address is a JSON object
if ( $claim eq "address" ) {
@ -1665,6 +1749,10 @@ Generate new Authorization Code session
Generate new Access Token session
=head2 newRefreshToken
Generate new Refresh Token session
=head2 getAuthorizationCode
Get existing Authorization Code session
@ -1673,6 +1761,10 @@ Get existing Authorization Code session
Get existing Access Token session
=head2 getRefreshToken
Get existing Refresh Token session
=head2 getOpenIDConnectSession
Try to recover the OpenID Connect session corresponding to id and return session

View File

@ -273,8 +273,9 @@
"yourKeyIsUnregistered":"تمت إزالة المفتاح",
"yourKeyIsVerified":"تم اختبار المفتاح الخاص بك بنجاح",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourOffline": "and access your account while you are offline",
"yourPhone":"رقم هاتفك",
"yourProfile":"ملفك الشخصي",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -184,7 +184,7 @@
"notFound":"Nicht gefunden: Du versuchst, auf eine nicht verfügbare Seite zuzugreifen",
"noTOTPFound":"Kein TOTP gefunden",
"noU2FKeyFound":"Kein U2F Schlüssel gefunden",
"oidcConsent":"Die Anwendung %s möchte wissen:",
"oidcConsent":"Die Anwendung %s möchte:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
@ -263,18 +263,19 @@
"warning":"Warnung",
"welcomeOnPortal":"Willkommen in Ihrem gesicherten Authentifizierungsportal.",
"yesResendMail":"Ja, Mail erneut senden.",
"yourAddress":"Ihre Adresse",
"yourAddress":"Wissen Ihre Adresse",
"yourApps":"Ihre Applikationen",
"yourEmail":"Ihre Mailadresse",
"yourIdentity":"Ihre Identität",
"yourEmail":"Wissen Ihre Mailadresse",
"yourIdentity":"Wissen Ihre Identität",
"yourIdentityIs":"Ihre Identität ist",
"yourKeyIsRegistered":"Ihr Key wurde registriert",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Ihr Key ist bestätigt",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Ihre Telefonnummer",
"yourProfile":"Ihr Profil",
"yourOffline": "and access your account while you are offline",
"yourPhone":"Wissen Ihre Telefonnummer",
"yourProfile":"Wissen Ihr Profil",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -184,7 +184,7 @@
"notFound": "Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"The application %s would like to know:",
"oidcConsent":"The application %s would like to:",
"oidcConsents": "OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
@ -263,18 +263,19 @@
"warning":"Warning",
"welcomeOnPortal":"Welcome on your secured authentication portal.",
"yesResendMail":"Yes, resend the mail",
"yourAddress":"Your address",
"yourAddress":"Know your address",
"yourApps":"Your applications",
"yourEmail":"Your email",
"yourIdentity":"Your identity",
"yourEmail":"Know your email",
"yourIdentity":"Know your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",
"yourOffline": "Access your account while you are offline",
"yourPhone":"Know your phone number",
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}

View File

@ -273,8 +273,9 @@
"yourKeyIsUnregistered":"Su llave ha sido suprimida",
"yourKeyIsVerified":"Su llave está verificada",
"yourNewTotpKey":"Su nueva llave TOTP, por favor pruébela e ingrese el código",
"yourOffline": "Access your account while you are offline",
"yourPhone":"Su número telefónico",
"yourProfile":"Su perfil",
"yourTotpKey":"Su llave TOTP",
"yubikey2f":"Yubikey"
}
}

View File

@ -184,7 +184,7 @@
"notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:",
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
@ -273,8 +273,9 @@
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourOffline": "and access your account while you are offline",
"yourPhone":"Puhelinnumerosi",
"yourProfile":"Profiilisi",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -184,7 +184,7 @@
"notFound": "Non trouvé : vous tentez d'accéder à une page non disponible",
"noTOTPFound":"Aucun secret TOTP trouvé",
"noU2FKeyFound": "Aucune clef U2F trouvée",
"oidcConsent":"L'application %s voudrait connaître :",
"oidcConsent":"L'application %s voudrait :",
"oidcConsents": "Accords OIDC",
"oidcConsentsFull":"Accords OpenID Connect",
"oneExpired2Fremoved":"Un second facteur expiré a été supprimé !",
@ -263,18 +263,19 @@
"warning":"Attention",
"welcomeOnPortal":"Bienvenue sur votre portail d'authentification sécurisée.",
"yesResendMail":"Oui, renvoyer le mail",
"yourAddress":"Votre adresse",
"yourAddress":"Connaître votre adresse",
"yourApps":"Vos applications",
"yourEmail":"Votre adresse électronique",
"yourIdentity":"Votre identité",
"yourEmail":"Connaître votre adresse électronique",
"yourIdentity":"Connaître votre identité",
"yourIdentityIs":"Votre identité est",
"yourKeyIsRegistered":"Votre clef est enregistrée",
"yourKeyIsAlreadyRegistered":"Votre clef est déjà enregistrée !",
"yourKeyIsUnregistered":"Votre clef a été supprimée",
"yourKeyIsVerified":"Votre clef est vérifiée",
"yourNewTotpKey":"Votre nouvelle clef TOTP. Testez-la et entrez le code",
"yourPhone":"Votre numéro de téléphone",
"yourProfile":"Vos informations personnelles",
"yourOffline": "Accéder à votre compte lorsque vous êtes hors-ligne",
"yourPhone":"Connaître votre numéro de téléphone",
"yourProfile":"Connaître vos informations personnelles",
"yourTotpKey":"Votre clef TOTP",
"yubikey2f":"Yubikey"
}

View File

@ -184,7 +184,7 @@
"notFound":"Non trovato: si tenta di accedere ad una pagina non disponibile",
"noTOTPFound":"Nessun TOTP trovato",
"noU2FKeyFound":"Nessuna chiave U2F trovata",
"oidcConsent":"L'applicazione %s vorrebbe sapere:",
"oidcConsent":"L'applicazione %s vorrebbe:",
"oidcConsents":"Consensi OIDC",
"oidcConsentsFull":"Consensi OpenID Connect",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
@ -263,18 +263,19 @@
"warning":"Avvertimento",
"welcomeOnPortal":"Benvenuto sul tuo portale di autenticazione protetta.",
"yesResendMail":"Sì, rinvia e-mail",
"yourAddress":"Il vostro indirizzo",
"yourAddress":"Sapere vostro indirizzo",
"yourApps":"Le vostre applicazioni",
"yourEmail":"E-mail",
"yourIdentity":"Identità",
"yourEmail":"Sapere vostro E-mail",
"yourIdentity":"Sapere vostro Identità",
"yourIdentityIs":"La tua identità é",
"yourKeyIsRegistered":"La vostra chiave è registrata",
"yourKeyIsAlreadyRegistered":"La tua chiave è GIÀ registrata !",
"yourKeyIsUnregistered":"La vostra chiave è stata rimossa",
"yourKeyIsVerified":"La tua chiave é stata testata con successo",
"yourNewTotpKey":"La tua nuova chiave TOTP, per favore provala e inserisci il codice",
"yourPhone":"Numero di telefono",
"yourProfile":"Il tuo profilo",
"yourOffline": "and access your account while you are offline",
"yourPhone":"Sapere vostro numero di telefono",
"yourProfile":"Sapere vostro profilo",
"yourTotpKey":"La tua chiave TOTP",
"yubikey2f":"Yubikey"
}
}

View File

@ -184,7 +184,7 @@
"notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:",
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
@ -263,18 +263,19 @@
"warning":"Warning",
"welcomeOnPortal":"Welcome on your secured authentication portal.",
"yesResendMail":"Yes, resend the mail",
"yourAddress":"Your address",
"yourAddress":"Know your address",
"yourApps":"Your applications",
"yourEmail":"Your email",
"yourIdentity":"Your identity",
"yourEmail":"Know your email",
"yourIdentity":"Know your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",
"yourOffline": "Access your account while you are offline",
"yourPhone":"Know your phone number",
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -184,7 +184,7 @@
"notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:",
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
@ -263,18 +263,19 @@
"warning":"Warning",
"welcomeOnPortal":"Welcome on your secured authentication portal.",
"yesResendMail":"Yes, resend the mail",
"yourAddress":"Your address",
"yourAddress":"Know your address",
"yourApps":"Your applications",
"yourEmail":"Your email",
"yourIdentity":"Your identity",
"yourEmail":"Know your email",
"yourIdentity":"Know your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",
"yourOffline": "Access your account while you are offline",
"yourPhone":"Know your phone number",
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -184,7 +184,7 @@
"notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:",
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
@ -263,18 +263,19 @@
"warning":"Warning",
"welcomeOnPortal":"Welcome on your secured authentication portal.",
"yesResendMail":"Yes, resend the mail",
"yourAddress":"Your address",
"yourAddress":"Know your address",
"yourApps":"Your applications",
"yourEmail":"Your email",
"yourIdentity":"Your identity",
"yourEmail":"Know your email",
"yourIdentity":"Know your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",
"yourOffline": "Access your account while you are offline",
"yourPhone":"Know your phone number",
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -273,8 +273,9 @@
"yourKeyIsUnregistered":"Khóa của bạn đã bị xóa",
"yourKeyIsVerified":"Chìa khóa của bạn đã được kiểm tra thành công",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourOffline": "and access your account while you are offline",
"yourPhone":"Số điện thoại của bạn",
"yourProfile":"Profile của bạn",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -184,7 +184,7 @@
"notFound":"无法找到:您请求的网页不存在。",
"noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:",
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
@ -273,8 +273,9 @@
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourOffline": "and access your account while you are offline",
"yourPhone":"您的电话号码",
"yourProfile":"您的档案",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -148,7 +148,7 @@ ok(
accept => 'text/html',
cookie => "lemonldap=$idpId",
),
"Get authorization code"
"Get authorization code for rp1"
);
count(1);
@ -168,17 +168,33 @@ ok(
HTTP_AUTHORIZATION => "Basic " . encode_base64("rp2id:rp2secret"),
},
),
"Post token"
"Post token on wrong RP"
);
count(1);
# Expect an invalid request
is( $res->[0], 400 );
is( $res->[0], 400, "Got invalid request" );
count(1);
# Get new code for RP1
my $query =
"response_type=code&scope=openid%20profile%20email&client_id=rpid&state=af0ifjsldkj&redirect_uri=http%3A%2F%2Frp.com%2F";
ok(
$res = $op->_get(
"/oauth2/authorize",
query => "$query",
accept => 'text/html',
cookie => "lemonldap=$idpId",
),
"Get authorization code again"
);
count(1);
my ($code) = expectRedirection( $res, qr#http://rp\.com/.*code=([^\&]*)# );
# Play code on RP1
$query =
"grant_type=authorization_code&code=$code&redirect_uri=http%3A%2F%2Frp2.com%2F";
"grant_type=authorization_code&code=$code&redirect_uri=http%3A%2F%2Frp.com%2F";
ok(
$res = $op->_post(
@ -190,7 +206,7 @@ ok(
HTTP_AUTHORIZATION => "Basic " . encode_base64("rpid:rpsecret"),
},
),
"Post token"
"Post auth code on correct RP"
);
count(1);
$res = expectJSON($res);
@ -209,10 +225,10 @@ ok(
HTTP_AUTHORIZATION => "Bearer " . $token,
},
),
"Post userinfo"
"post to userinfo with expired access token"
);
count(1);
is( $res->[0], 401, "Access denied with expired token" );
ok( $res->[0] == 401, "Access denied with expired token" );
count(1);
clean_sessions();