Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
lemonldap-ng
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Service Desk
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Maxime Besson
lemonldap-ng
Commits
ec834145
Commit
ec834145
authored
Dec 17, 2016
by
Yadd
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SAML in progress (#595)
To do: authSAML SOAP server
parent
8e2418ce
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
187 additions
and
28 deletions
+187
-28
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm
+120
-5
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm
+8
-15
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm
+3
-1
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm
+2
-2
lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Artifact.t
lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Artifact.t
+2
-2
lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t
...-ng-portal/t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t
+52
-3
No files found.
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm
View file @
ec834145
...
...
@@ -19,10 +19,11 @@ our $VERSION = '2.0.0';
extends
'
Lemonldap::NG::Portal::Main::Issuer
',
'
Lemonldap::NG::Portal::Lib::SAML
';
has
ssoUrlRe
=>
(
is
=>
'
rw
'
);
has
sloRe
=>
(
is
=>
'
rw
'
);
has
artRe
=>
(
is
=>
'
rw
'
);
has
soapSloRe
=>
(
is
=>
'
rw
'
);
has
ssoUrlRe
=>
(
is
=>
'
rw
'
);
has
sloRe
=>
(
is
=>
'
rw
'
);
has
artRe
=>
(
is
=>
'
rw
'
);
has
soapSloRe
=>
(
is
=>
'
rw
'
);
has
sloRelaySoapRe
=>
(
is
=>
'
rw
'
);
# INITIALIZATION
...
...
@@ -76,6 +77,8 @@ qr/^($saml_sso_soap_url|$saml_sso_soap_url_ret|$saml_sso_get_url|$saml_sso_get_u
qr/^($saml_slo_soap_url|$saml_slo_soap_url_ret|$saml_slo_get_url|$saml_slo_get_url_ret|$saml_slo_post_url|$saml_slo_post_url_ret)(?:\?.*)?$/
i
);
$self
->
sloRelaySoapRe
(
qr#^/saml/relaySingleLogoutSOAP(?:\?.*)?$#
i
);
return
(
$self
->
Lemonldap::NG::Portal::Main::Issuer::
init
()
...
...
@@ -104,7 +107,20 @@ sub _pRedirect {
return
$self
->
soapSloServer
(
$req
);
}
else
{
return
$self
->
SUPER::
_pRedirect
(
$req
);
$req
->
parseBody
;
return
$self
->
SUPER::
_redirect
(
$req
);
}
}
# Override _redirect to catch SLO relay
sub
_redirect
{
my
(
$self
,
$req
)
=
@_
;
if
(
$req
->
uri
=~
$self
->
sloRelaySoapRe
)
{
return
$self
->
sloRelaySoap
(
$req
);
}
else
{
return
$self
->
SUPER::
_redirect
(
$req
);
}
}
...
...
@@ -1461,6 +1477,105 @@ sub logout {
return
PE_OK
;
}
sub
sloRelaySoap
{
my
(
$self
,
$req
)
=
@_
;
$self
->
lmLog
(
"
URL
"
.
$req
->
uri
.
"
detected as a SOAP relay service URL
",
'
debug
'
);
# Check if relay parameter is present (mandatory)
my
$relayID
;
unless
(
$relayID
=
$req
->
param
('
relay
')
)
{
$self
->
lmLog
(
"
No relayID detected
",
'
error
'
);
return
$self
->
imgnok
(
$req
);
}
# Retrieve the corresponding data from samlStorage
my
$relayInfos
=
$self
->
getSamlSession
(
$relayID
);
unless
(
$relayInfos
)
{
$self
->
lmLog
(
"
Could not get relay session
$relayID
",
'
error
'
);
return
$self
->
imgnok
(
$req
);
}
$self
->
lmLog
(
"
Found relay session
$relayID
",
'
debug
'
);
# Rebuild the logout object
my
$logout
;
unless
(
$logout
=
$self
->
createLogout
(
$self
->
lassoServer
)
)
{
$self
->
lmLog
(
"
Could not rebuild logout object
",
'
error
'
);
return
$self
->
imgnok
(
$req
);
}
# Load Session and Identity if they exist
my
$session
=
$relayInfos
->
data
->
{
_lassoSessionDump
};
my
$identity
=
$relayInfos
->
data
->
{
_lassoIdentityDump
};
my
$providerID
=
$relayInfos
->
data
->
{
_providerID
};
my
$relayState
=
$relayInfos
->
data
->
{
_relayState
};
my
$spConfKey
=
$self
->
spList
->
{
$providerID
}
->
{
confKey
};
if
(
$session
)
{
unless
(
$self
->
setSessionFromDump
(
$logout
,
$session
)
)
{
$self
->
lmLog
(
"
Unable to load Lasso Session
",
'
error
'
);
return
$self
->
imgnok
(
$req
);
}
$self
->
lmLog
(
"
Lasso Session loaded
",
'
debug
'
);
}
if
(
$identity
)
{
unless
(
$self
->
setIdentityFromDump
(
$logout
,
$identity
)
)
{
$self
->
lmLog
(
"
Unable to load Lasso Identity
",
'
error
'
);
return
$self
->
imgnok
(
$req
);
}
$self
->
lmLog
(
"
Lasso Identity loaded
",
'
debug
'
);
}
# Send the logout request
my
(
$rstatus
,
$rmethod
,
$rinfo
)
=
$self
->
sendLogoutRequestToProvider
(
$req
,
$logout
,
$providerID
,
Lasso::Constants::
HTTP_METHOD_SOAP
);
unless
(
$rstatus
)
{
$self
->
lmLog
(
"
Fail to process SOAP logout request to
$providerID
",
'
error
'
);
return
$self
->
imgnok
(
$req
);
}
# Store success status for this SLO request
my
$sloStatusSessionInfos
=
$self
->
getSamlSession
(
$relayState
);
if
(
$sloStatusSessionInfos
)
{
$sloStatusSessionInfos
->
update
(
{
$spConfKey
=>
1
}
);
$self
->
lmLog
(
"
Store SLO status for
$spConfKey
in session
$relayState
",
'
debug
'
);
}
else
{
$self
->
lmLog
(
"
Unable to store SLO status for
$spConfKey
in session
$relayState
",
'
warn
'
);
}
# Delete relay session
$relayInfos
->
remove
();
# SLO response is OK
$self
->
lmLog
(
"
Display OK status for SLO on
$spConfKey
",
'
debug
'
);
return
$self
->
imgok
(
$req
);
}
# INTERNAL METHODS
sub
imgok
{
my
(
$self
,
$req
,
)
=
@_
;
return
$self
->
sendImage
(
$req
,
'
ok.png
'
);
}
sub
imgnok
{
my
(
$self
,
$req
,
)
=
@_
;
return
$self
->
sendImage
(
$req
,
'
warning.png
'
);
}
sub
sendImage
{
my
(
$self
,
$req
,,
$img
)
=
@_
;
return
$self
->
p
->
staticFile
(
$req
,
"
common/
$img
",
'
image/png
'
);
}
1
;
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm
View file @
ec834145
...
...
@@ -61,15 +61,8 @@ sub display {
# 1. Good authentication
# 1.1 Image mode
if
(
$req
->
{
error
}
==
PE_IMG_OK
||
$req
->
{
error
}
==
PE_IMG_NOK
)
{
$self
->
lmLog
(
'
Request for file
',
'
debug
'
);
return
staticFile
(
"
common/
"
.
(
$req
->
{
error
}
==
PE_IMG_OK
?
'
ok.png
'
:
'
warning.png
'
)
);
}
# 1.2 Case : there is a message to display
elsif
(
my
$info
=
$req
->
info
()
)
{
# 1.1 Case : there is a message to display
if
(
my
$info
=
$req
->
info
()
)
{
$skinfile
=
'
info
';
%templateParams
=
(
AUTH_ERROR_TYPE
=>
$req
->
error_type
,
...
...
@@ -81,7 +74,7 @@ sub display {
);
}
# 1.
3
Redirection
# 1.
2
Redirection
elsif
(
$req
->
{
error
}
==
PE_REDIRECT
)
{
$skinfile
=
"
redirect
";
%templateParams
=
(
...
...
@@ -91,7 +84,7 @@ sub display {
);
}
# 1.
4
Case : display menu
# 1.
3
Case : display menu
elsif
(
$req
->
error
==
PE_OK
)
{
$skinfile
=
'
menu
';
...
...
@@ -110,8 +103,8 @@ sub display {
# 2. Authentication not complete
# 2.1 A notification has to be done (session is created but hidden and unusable
#
until the user has accept the message)
# 2.1 A notification has to be done (session is created but hidden and
# unusable
until the user has accept the message)
elsif
(
my
$notif
=
$req
->
datas
->
{
notification
}
)
{
$skinfile
=
'
notification
';
%templateParams
=
(
...
...
@@ -344,12 +337,12 @@ sub display {
# @param $type The content-type to use (ie: image/png)
# @return void
sub
staticFile
{
my
(
$self
,
$file
,
$type
)
=
@_
;
my
(
$self
,
$
req
,
$
file
,
$type
)
=
@_
;
require
Plack::
Util
;
require
Cwd
;
require
HTTP::
Date
;
open
my
$fh
,
'
<:raw
',
$self
->
conf
->
{
templatesDir
}
.
"
/
$file
"
or
return
$self
->
sendError
(
$!
,
403
);
or
return
$self
->
sendError
(
$
req
,
$
!
,
403
);
my
@stat
=
stat
$file
;
Plack::Util::
set_io_path
(
$fh
,
Cwd::
realpath
(
$file
)
);
return
[
...
...
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm
View file @
ec834145
...
...
@@ -127,7 +127,9 @@ sub loginInfo {
}
sub
info
{
print
STDERR
"
TODO Request::info()
\n
";
my
(
$self
,
$info
)
=
@_
;
$self
->
datas
->
{
_info
}
.=
$info
if
(
defined
$info
);
return
$self
->
datas
->
{
_info
};
}
# TODO: oldpassword
...
...
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm
View file @
ec834145
...
...
@@ -583,8 +583,8 @@ sub getFirstValue {
}
sub
info
{
my
(
$self
,
$req
,
$info
)
=
@_
;
print
STDERR
"
####### TODO: info()
\n
"
;
my
(
$self
,
$req
,
$info
)
=
@_
;
return
$req
->
info
(
$info
)
;
}
1
;
lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Artifact.t
View file @
ec834145
...
...
@@ -7,7 +7,7 @@ BEGIN {
require
'
t/test-lib.pm
';
}
my
$maintests
=
2
8
;
my
$maintests
=
2
6
;
my
$debug
=
'
error
';
my
(
$issuer
,
$sp
,
$res
);
my
%handlerOR
=
(
issuer
=>
[]
,
sp
=>
[]
);
...
...
@@ -220,7 +220,7 @@ sub LWP::UserAgent::request {
$httpResp
->
header
(
$name
,
shift
(
@
{
$res
->
[
1
]
}
)
);
}
$httpResp
->
content
(
join
(
'',
@
{
$res
->
[
2
]
}
)
);
count
(
3
);
count
(
4
);
return
$httpResp
;
}
...
...
lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t
View file @
ec834145
...
...
@@ -7,7 +7,7 @@ BEGIN {
require
'
t/test-lib.pm
';
}
my
$maintests
=
18
;
my
$maintests
=
21
;
my
$debug
=
'
debug
';
my
(
$issuer
,
$sp
,
$res
);
my
%handlerOR
=
(
issuer
=>
[]
,
sp
=>
[]
);
...
...
@@ -104,17 +104,65 @@ SKIP: {
cookie
=>
"
lemonldap=
$idpId
",
accept
=>
'
text/html
'
),
'
Query
S
P for logout
'
'
Query
Id
P for logout
'
);
ok
(
$res
->
[
0
]
==
200
,
'
Return code is 200
'
);
#print STDERR Dumper($res);
ok
(
$res
->
[
2
]
->
[
0
]
=~
m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s
,
'
Get image request
'
);
ok
(
$res
=
$issuer
->
_get
(
$
1
,
query
=>
$
2
,
#cookie => "lemonldap=$idpId",
accept
=>
'
text/html
'
),
'
Get image
'
);
ok
(
$issuer
->
getHeader
(
$res
,
'
Content-Type
'
)
eq
'
image/png
',
'
Get an image
'
);
}
count
(
$maintests
);
clean_sessions
();
done_testing
(
count
()
);
# Redefine LWP methods for tests
sub
LWP
::UserAgent::request {
my
(
$self
,
$req
)
=
@_
;
ok
(
$req
->
uri
=~
m#http://auth.sp.com(.*)#
,
'
Request from SP to IdP
'
);
my
$url
=
$
1
;
my
$res
;
my
$s
=
$req
->
content
;
ok
(
$res
=
$sp
->
_post
(
$url
,
IO::
String
->
new
(
$s
),
length
=>
length
(
$s
),
type
=>
'
application/xml
',
),
'
Execute request
'
);
#ok( ( $res->[0] == 200 or $res->[0] == 400 ), 'Response is 200 or 400' )
# or explain( $res->[0], "200 or 400" );
#ok( $issuer->getHeader( $res, 'Content-Type' ) =~ m#^application/xml#,
# 'Content is XML' )
# or explain( $res->[1], 'Content-Type => application/xml' );
my
$httpResp
=
HTTP::
Response
->
new
(
$res
->
[
0
],
'
OK
'
);
while
(
my
$name
=
shift
@
{
$res
->
[
1
]
}
)
{
$httpResp
->
header
(
$name
,
shift
(
@
{
$res
->
[
1
]
}
)
);
}
$httpResp
->
content
(
join
(
'',
@
{
$res
->
[
2
]
}
)
);
count
(
2
);
return
$httpResp
;
}
sub
switch
{
my
$type
=
shift
;
@
Lemonldap::NG::Handler::Main::Reload::
_onReload
=
@
{
...
...
@@ -127,6 +175,7 @@ sub issuer {
{
ini
=>
{
logLevel
=>
$debug
,
templatesDir
=>
'
site/htdocs/static
',
domain
=>
'
idp.com
',
portal
=>
'
http://auth.idp.com
',
authentication
=>
'
Demo
',
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment