Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
reg-app
Regapp
Commits
d9b721d6
Commit
d9b721d6
authored
May 11, 2021
by
michael.simon
Browse files
Refactor SAML SP dispatcher Mechanism
parent
43116b69
Changes
6
Hide whitespace changes
Inline
Side-by-side
bwreg-service/src/main/java/edu/kit/scc/webreg/service/saml/SamlSpLogoutServiceImpl.java
View file @
d9b721d6
package
edu.kit.scc.webreg.service.saml
;
import
java.time.Instant
;
import
java.util.Date
;
import
java.io.IOException
;
import
java.security.PrivateKey
;
import
java.security.cert.X509Certificate
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
javax.ejb.Stateless
;
import
javax.inject.Inject
;
...
...
@@ -14,39 +15,38 @@ import org.joda.time.DateTime;
import
org.opensaml.messaging.context.MessageContext
;
import
org.opensaml.saml.common.SAMLObject
;
import
org.opensaml.saml.common.SAMLVersion
;
import
org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport
;
import
org.opensaml.saml.common.messaging.context.SAMLEndpointContext
;
import
org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext
;
import
org.opensaml.saml.common.xml.SAMLConstants
;
import
org.opensaml.saml.criterion.RoleDescriptorCriterion
;
import
org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder
;
import
org.opensaml.saml.saml2.core.Assertion
;
import
org.opensaml.saml.saml2.core.AuthnRequest
;
import
org.opensaml.saml.saml2.core.Issuer
;
import
org.opensaml.saml.saml2.core.LogoutRequest
;
import
org.opensaml.saml.saml2.core.NameID
;
import
org.opensaml.saml.saml2.core.Response
;
import
org.opensaml.saml.saml2.metadata.EntityDescriptor
;
import
org.opensaml.saml.saml2.metadata.SingleLogoutService
;
import
org.opensaml.saml.saml2.metadata.SingleSignOnService
;
import
org.opensaml.saml.security.impl.SAMLMetadataSignatureSigningParametersResolver
;
import
org.opensaml.security.credential.Credential
;
import
org.opensaml.security.x509.BasicX509Credential
;
import
org.opensaml.xmlsec.SignatureSigningParameters
;
import
org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap
;
import
org.opensaml.xmlsec.context.SecurityParametersContext
;
import
org.opensaml.xmlsec.criterion.SignatureSigningConfigurationCriterion
;
import
org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration
;
import
org.slf4j.Logger
;
import
org.slf4j.MDC
;
import
edu.kit.scc.webreg.bootstrap.ApplicationConfig
;
import
edu.kit.scc.webreg.dao.SamlIdpMetadataDao
;
import
edu.kit.scc.webreg.dao.SamlSpConfigurationDao
;
import
edu.kit.scc.webreg.dao.SamlUserDao
;
import
edu.kit.scc.webreg.dao.UserLoginInfoDao
;
import
edu.kit.scc.webreg.drools.impl.KnowledgeSessionSingleton
;
import
edu.kit.scc.webreg.entity.SamlIdpMetadataEntity
;
import
edu.kit.scc.webreg.entity.SamlIdpMetadataEntityStatus
;
import
edu.kit.scc.webreg.entity.SamlSpConfigurationEntity
;
import
edu.kit.scc.webreg.entity.SamlUserEntity
;
import
edu.kit.scc.webreg.entity.UserEntity
;
import
edu.kit.scc.webreg.entity.UserLoginInfoEntity
;
import
edu.kit.scc.webreg.entity.UserLoginInfoStatus
;
import
edu.kit.scc.webreg.entity.UserLoginMethod
;
import
edu.kit.scc.webreg.exc.UserUpdateException
;
import
edu.kit.scc.webreg.service.impl.UserUpdater
;
import
edu.kit.scc.webreg.service.saml.exc.SamlAuthenticationException
;
import
edu.kit.scc.webreg.session.SessionManager
;
import
net.shibboleth.utilities.java.support.resolver.CriteriaSet
;
@Stateless
public
class
SamlSpLogoutServiceImpl
implements
SamlSpLogoutService
{
...
...
@@ -57,6 +57,9 @@ public class SamlSpLogoutServiceImpl implements SamlSpLogoutService {
@Inject
private
SamlIdpMetadataDao
idpDao
;
@Inject
private
SamlSpConfigurationDao
spConfigDao
;
@Inject
private
SamlUserDao
userDao
;
...
...
@@ -66,6 +69,9 @@ public class SamlSpLogoutServiceImpl implements SamlSpLogoutService {
@Inject
private
MetadataHelper
metadataHelper
;
@Inject
private
CryptoHelper
cryptoHelper
;
@Inject
private
ApplicationConfig
appConfig
;
...
...
@@ -91,6 +97,7 @@ public class SamlSpLogoutServiceImpl implements SamlSpLogoutService {
SamlUserEntity
user
=
(
SamlUserEntity
)
tempUser
;
SamlIdpMetadataEntity
idpEntity
=
user
.
getIdp
();
SamlSpConfigurationEntity
spEntity
=
spConfigDao
.
findByHostname
(
request
.
getLocalName
());
EntityDescriptor
entityDesc
=
samlHelper
.
unmarshal
(
idpEntity
.
getEntityDescriptor
(),
EntityDescriptor
.
class
);
...
...
@@ -100,6 +107,7 @@ public class SamlSpLogoutServiceImpl implements SamlSpLogoutService {
logoutRequest
.
setID
(
samlHelper
.
getRandomId
());
logoutRequest
.
setVersion
(
SAMLVersion
.
VERSION_20
);
logoutRequest
.
setIssueInstant
(
new
DateTime
());
logoutRequest
.
setDestination
(
slo
.
getLocation
());
NameID
nameId
=
samlHelper
.
create
(
NameID
.
class
,
NameID
.
DEFAULT_ELEMENT_NAME
);
nameId
.
setFormat
(
NameID
.
PERSISTENT
);
...
...
@@ -112,10 +120,6 @@ public class SamlSpLogoutServiceImpl implements SamlSpLogoutService {
logger
.
debug
(
"Logout Request: {}"
,
samlHelper
.
prettyPrint
(
logoutRequest
));
/**
* Need to sign logout message. Doesn't get accepted unsigned.
*/
MessageContext
<
SAMLObject
>
messageContext
=
new
MessageContext
<
SAMLObject
>();
messageContext
.
setMessage
(
logoutRequest
);
SAMLPeerEntityContext
entityContext
=
new
SAMLPeerEntityContext
();
...
...
@@ -124,6 +128,38 @@ public class SamlSpLogoutServiceImpl implements SamlSpLogoutService {
endpointContext
.
setEndpoint
(
slo
);
entityContext
.
addSubcontext
(
endpointContext
);
messageContext
.
addSubcontext
(
entityContext
);
/**
* Need to sign logout message. Doesn't get accepted unsigned.
*/
PrivateKey
privateKey
;
X509Certificate
publicKey
;
try
{
privateKey
=
cryptoHelper
.
getPrivateKey
(
spEntity
.
getPrivateKey
());
publicKey
=
cryptoHelper
.
getCertificate
(
spEntity
.
getCertificate
());
}
catch
(
IOException
e
)
{
throw
new
SamlAuthenticationException
(
"Private key is not set up properly"
,
e
);
}
BasicX509Credential
credential
=
new
BasicX509Credential
(
publicKey
,
privateKey
);
List
<
Credential
>
credentialList
=
new
ArrayList
<
Credential
>();
credentialList
.
add
(
credential
);
BasicSignatureSigningConfiguration
ssConfig
=
DefaultSecurityConfigurationBootstrap
.
buildDefaultSignatureSigningConfiguration
();
ssConfig
.
setSigningCredentials
(
credentialList
);
CriteriaSet
criteriaSet
=
new
CriteriaSet
();
criteriaSet
.
add
(
new
SignatureSigningConfigurationCriterion
(
ssConfig
));
criteriaSet
.
add
(
new
RoleDescriptorCriterion
(
entityDesc
.
getIDPSSODescriptor
(
SAMLConstants
.
SAML20P_NS
)));
SAMLMetadataSignatureSigningParametersResolver
smsspr
=
new
SAMLMetadataSignatureSigningParametersResolver
();
SignatureSigningParameters
ssp
=
smsspr
.
resolveSingle
(
criteriaSet
);
logger
.
debug
(
"Resolved algo {} for signing"
,
ssp
.
getSignatureAlgorithm
());
SecurityParametersContext
securityContext
=
new
SecurityParametersContext
();
securityContext
.
setSignatureSigningParameters
(
ssp
);
messageContext
.
addSubcontext
(
securityContext
);
SAMLMessageSecuritySupport
.
signMessage
(
messageContext
);
HTTPRedirectDeflateEncoder
encoder
=
new
HTTPRedirectDeflateEncoder
();
encoder
.
setHttpServletResponse
(
response
);
...
...
bwreg-webapp/src/main/java/edu/kit/scc/webreg/bean/LogoutBean.java
View file @
d9b721d6
...
...
@@ -65,7 +65,7 @@ public class LogoutBean implements Serializable {
public
void
startLogout
()
{
try
{
FacesContext
.
getCurrentInstance
().
getExternalContext
().
redirect
(
"/logout/
all
"
);
FacesContext
.
getCurrentInstance
().
getExternalContext
().
redirect
(
"/logout/
saml?user_id=1009
"
);
}
catch
(
IOException
e
)
{
logger
.
warn
(
"Redirect failed"
,
e
);
}
...
...
bwreg-webapp/src/main/java/edu/kit/scc/webreg/sec/Saml2AttributeQueryHandler.java
View file @
d9b721d6
...
...
@@ -12,9 +12,14 @@ package edu.kit.scc.webreg.sec;
import
java.io.IOException
;
import
javax.enterprise.context.ApplicationScoped
;
import
javax.inject.Inject
;
import
javax.inject.Named
;
import
javax.servlet.Servlet
;
import
javax.servlet.ServletConfig
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.annotation.WebServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
...
...
@@ -43,6 +48,7 @@ import edu.kit.scc.webreg.bootstrap.ApplicationConfig;
import
edu.kit.scc.webreg.entity.SamlAAConfigurationEntity
;
import
edu.kit.scc.webreg.entity.SamlSpMetadataEntity
;
import
edu.kit.scc.webreg.entity.UserEntity
;
import
edu.kit.scc.webreg.service.SamlAAConfigurationService
;
import
edu.kit.scc.webreg.service.SamlSpMetadataService
;
import
edu.kit.scc.webreg.service.UserService
;
import
edu.kit.scc.webreg.service.saml.Saml2DecoderService
;
...
...
@@ -52,8 +58,9 @@ import edu.kit.scc.webreg.service.saml.SsoHelper;
import
edu.kit.scc.webreg.service.saml.exc.SamlAuthenticationException
;
import
net.shibboleth.utilities.java.support.component.ComponentInitializationException
;
@ApplicationScoped
public
class
Saml2AttributeQueryHandler
{
@Named
@WebServlet
(
urlPatterns
=
{
"/Shibboleth.sso/SAML2/AttributeQuery"
,
"/saml/sp/attribute-query"
})
public
class
Saml2AttributeQueryHandler
implements
Servlet
{
@Inject
private
Logger
logger
;
...
...
@@ -70,6 +77,9 @@ public class Saml2AttributeQueryHandler {
@Inject
private
SamlSpMetadataService
spMetadataService
;
@Inject
private
SamlAAConfigurationService
aaConfigService
;
@Inject
private
UserService
userService
;
...
...
@@ -79,7 +89,33 @@ public class Saml2AttributeQueryHandler {
@Inject
private
ApplicationConfig
appConfig
;
public
void
service
(
HttpServletRequest
request
,
HttpServletResponse
response
,
SamlAAConfigurationEntity
aaConfig
)
@Override
public
void
service
(
ServletRequest
servletRequest
,
ServletResponse
servletResponse
)
throws
ServletException
,
IOException
{
HttpServletRequest
request
=
(
HttpServletRequest
)
servletRequest
;
HttpServletResponse
response
=
(
HttpServletResponse
)
servletResponse
;
String
context
=
request
.
getServletContext
().
getContextPath
();
String
path
=
request
.
getRequestURI
().
substring
(
context
.
length
());
logger
.
debug
(
"Dispatching request context '{}' path '{}'"
,
context
,
path
);
SamlAAConfigurationEntity
aaConfig
=
aaConfigService
.
findByHostname
(
request
.
getServerName
());
if
(
aaConfig
!=
null
&&
aaConfig
.
getAq
()
!=
null
&&
aaConfig
.
getAq
().
endsWith
(
context
+
path
))
{
logger
.
debug
(
"Executing AttributeQuery Handler for entity {}"
,
aaConfig
.
getEntityId
());
service
(
request
,
response
,
aaConfig
);
return
;
}
logger
.
info
(
"No matching servlet for context '{}' path '{}'"
,
context
,
path
);
}
private
void
service
(
HttpServletRequest
request
,
HttpServletResponse
response
,
SamlAAConfigurationEntity
aaConfig
)
throws
ServletException
,
IOException
{
logger
.
debug
(
"Consuming SAML AttributeQuery"
);
...
...
@@ -204,4 +240,23 @@ public class Saml2AttributeQueryHandler {
return
attribute
;
}
@Override
public
void
init
(
ServletConfig
config
)
throws
ServletException
{
}
@Override
public
ServletConfig
getServletConfig
()
{
return
null
;
}
@Override
public
String
getServletInfo
()
{
return
null
;
}
@Override
public
void
destroy
()
{
}
}
bwreg-webapp/src/main/java/edu/kit/scc/webreg/sec/Saml2PostHandler.java
View file @
d9b721d6
...
...
@@ -12,20 +12,27 @@ package edu.kit.scc.webreg.sec;
import
java.io.IOException
;
import
javax.enterprise.context.ApplicationScoped
;
import
javax.inject.Inject
;
import
javax.inject.Named
;
import
javax.servlet.Servlet
;
import
javax.servlet.ServletConfig
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.annotation.WebServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.slf4j.Logger
;
import
edu.kit.scc.webreg.entity.SamlSpConfigurationEntity
;
import
edu.kit.scc.webreg.service.SamlSpConfigurationService
;
import
edu.kit.scc.webreg.service.saml.SamlSpPostService
;
import
edu.kit.scc.webreg.session.SessionManager
;
@ApplicationScoped
public
class
Saml2PostHandler
{
@Named
@WebServlet
(
urlPatterns
=
{
"/Shibboleth.sso/SAML2/POST"
,
"/saml/sp/post"
})
public
class
Saml2PostHandler
implements
Servlet
{
@Inject
private
Logger
logger
;
...
...
@@ -33,10 +40,34 @@ public class Saml2PostHandler {
@Inject
private
SessionManager
session
;
@Inject
private
SamlSpConfigurationService
spConfigService
;
@Inject
private
SamlSpPostService
spPostService
;
@Override
public
void
service
(
ServletRequest
servletRequest
,
ServletResponse
servletResponse
)
throws
ServletException
,
IOException
{
HttpServletRequest
request
=
(
HttpServletRequest
)
servletRequest
;
HttpServletResponse
response
=
(
HttpServletResponse
)
servletResponse
;
String
context
=
request
.
getServletContext
().
getContextPath
();
String
path
=
request
.
getRequestURI
().
substring
(
context
.
length
());
logger
.
debug
(
"Dispatching request context '{}' path '{}'"
,
context
,
path
);
SamlSpConfigurationEntity
spConfig
=
spConfigService
.
findByHostname
(
request
.
getServerName
());
if
(
spConfig
!=
null
)
{
logger
.
debug
(
"Executing POST Handler for entity {}"
,
spConfig
.
getEntityId
());
service
(
request
,
response
,
spConfig
);
}
}
p
ublic
void
service
(
HttpServletRequest
request
,
HttpServletResponse
response
,
SamlSpConfigurationEntity
spConfig
)
p
rivate
void
service
(
HttpServletRequest
request
,
HttpServletResponse
response
,
SamlSpConfigurationEntity
spConfig
)
throws
ServletException
,
IOException
{
if
(
session
==
null
||
session
.
getIdpId
()
==
null
||
session
.
getSpId
()
==
null
)
{
...
...
@@ -78,4 +109,23 @@ public class Saml2PostHandler {
}
}
}
@Override
public
void
init
(
ServletConfig
config
)
throws
ServletException
{
}
@Override
public
ServletConfig
getServletConfig
()
{
return
null
;
}
@Override
public
String
getServletInfo
()
{
return
null
;
}
@Override
public
void
destroy
()
{
}
}
bwreg-webapp/src/main/java/edu/kit/scc/webreg/sec/SamlSpDispatcherServlet.java
deleted
100644 → 0
View file @
43116b69
/*******************************************************************************
* Copyright (c) 2014 Michael Simon.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Michael Simon - initial
******************************************************************************/
package
edu.kit.scc.webreg.sec
;
import
java.io.IOException
;
import
javax.inject.Inject
;
import
javax.inject.Named
;
import
javax.servlet.Servlet
;
import
javax.servlet.ServletConfig
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.annotation.WebServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.slf4j.Logger
;
import
edu.kit.scc.webreg.entity.SamlAAConfigurationEntity
;
import
edu.kit.scc.webreg.entity.SamlSpConfigurationEntity
;
import
edu.kit.scc.webreg.service.SamlAAConfigurationService
;
import
edu.kit.scc.webreg.service.SamlSpConfigurationService
;
@Named
@WebServlet
(
urlPatterns
=
{
"/Shibboleth.sso/*"
,
"/saml/sp/*"
})
public
class
SamlSpDispatcherServlet
implements
Servlet
{
@Inject
private
Logger
logger
;
@Inject
private
SamlSpConfigurationService
spConfigService
;
@Inject
private
SamlAAConfigurationService
aaConfigService
;
@Inject
private
Saml2AttributeQueryHandler
attributeQueryServlet
;
@Inject
private
Saml2PostHandler
postHandler
;
@Override
public
void
init
(
ServletConfig
config
)
throws
ServletException
{
}
@Override
public
void
service
(
ServletRequest
servletRequest
,
ServletResponse
servletResponse
)
throws
ServletException
,
IOException
{
HttpServletRequest
request
=
(
HttpServletRequest
)
servletRequest
;
HttpServletResponse
response
=
(
HttpServletResponse
)
servletResponse
;
String
context
=
request
.
getServletContext
().
getContextPath
();
String
path
=
request
.
getRequestURI
().
substring
(
context
.
length
());
logger
.
debug
(
"Dispatching request context '{}' path '{}'"
,
context
,
path
);
SamlSpConfigurationEntity
spConfig
=
spConfigService
.
findByHostname
(
request
.
getServerName
());
if
(
spConfig
!=
null
&&
spConfig
.
getAcs
()
!=
null
&&
spConfig
.
getAcs
().
endsWith
(
context
+
path
))
{
logger
.
debug
(
"Executing POST Handler for entity {}"
,
spConfig
.
getEntityId
());
postHandler
.
service
(
request
,
response
,
spConfig
);
return
;
}
SamlAAConfigurationEntity
aaConfig
=
aaConfigService
.
findByHostname
(
request
.
getServerName
());
if
(
aaConfig
!=
null
&&
aaConfig
.
getAq
()
!=
null
&&
aaConfig
.
getAq
().
endsWith
(
context
+
path
))
{
logger
.
debug
(
"Executing AttributeQuery Handler for entity {}"
,
aaConfig
.
getEntityId
());
attributeQueryServlet
.
service
(
request
,
response
,
aaConfig
);
return
;
}
logger
.
info
(
"No matching servlet for context '{}' path '{}'"
,
context
,
path
);
}
@Override
public
ServletConfig
getServletConfig
()
{
return
null
;
}
@Override
public
String
getServletInfo
()
{
return
null
;
}
@Override
public
void
destroy
()
{
}
}
bwreg-webapp/src/main/webapp/user/logout.xhtml
View file @
d9b721d6
...
...
@@ -24,6 +24,7 @@
<p:dataTable
value=
"#{logoutBean.userLoginList}"
var=
"userLogin"
>
<p:column>
#{userLogin.id}
</p:column>
<p:column><a
href=
"/logout/saml?user_id=#{userLogin.id}"
>
Logout
</a></p:column>
</p:dataTable>
<p:panel
id=
"logoutPanel"
>
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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