Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
dariah
dariahsp
Commits
fb0687c7
Commit
fb0687c7
authored
Nov 04, 2020
by
Gradl, Tobias
Browse files
9: Finalize SAML related behavior
Task-Url:
#9
parent
b146719c
Pipeline
#17633
passed with stage
in 1 minute and 55 seconds
Changes
12
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/authenticator/BaseProfileCreator.java
0 → 100644
View file @
fb0687c7
package
eu.dariah.de.dariahsp.authenticator
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Set
;
import
eu.dariah.de.dariahsp.config.model.RoleDefinition
;
import
eu.dariah.de.dariahsp.model.ExtendedUserProfile
;
import
lombok.Data
;
@Data
public
abstract
class
BaseProfileCreator
{
public
static
final
String
ROLE_PREFIX
=
"ROLE_"
;
protected
final
String
clientName
;
protected
List
<
RoleDefinition
>
roleDefinitions
;
protected
Set
<
RoleDefinition
>
getMappedRoles
(
ExtendedUserProfile
profile
)
{
Set
<
RoleDefinition
>
roles
=
new
LinkedHashSet
<>();
for
(
RoleDefinition
rm
:
roleDefinitions
)
{
for
(
String
client
:
rm
.
getMappings
().
keySet
())
{
if
(!
client
.
equals
(
clientName
))
{
continue
;
}
for
(
String
extRole
:
profile
.
getExternalRoles
())
{
if
(!
extRole
.
trim
().
isEmpty
()
&&
rm
.
getMappings
().
get
(
client
).
contains
(
extRole
.
trim
())
&&
!
roles
.
contains
(
rm
))
{
roles
.
add
(
rm
);
}
}
}
}
return
roles
;
}
}
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/authenticator/LocalProfileCreator.java
0 → 100644
View file @
fb0687c7
package
eu.dariah.de.dariahsp.authenticator
;
import
java.util.Optional
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
org.pac4j.core.context.WebContext
;
import
org.pac4j.core.credentials.UsernamePasswordCredentials
;
import
org.pac4j.core.profile.UserProfile
;
import
org.pac4j.core.profile.creator.ProfileCreator
;
import
eu.dariah.de.dariahsp.config.model.RoleDefinition
;
import
eu.dariah.de.dariahsp.model.ExtendedUserProfile
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
@Data
@EqualsAndHashCode
(
callSuper
=
false
)
public
class
LocalProfileCreator
extends
BaseProfileCreator
implements
ProfileCreator
<
UsernamePasswordCredentials
>
{
public
LocalProfileCreator
(
String
clientName
)
{
super
(
clientName
);
}
@Override
public
Optional
<
UserProfile
>
create
(
final
UsernamePasswordCredentials
credentials
,
final
WebContext
context
)
{
if
(
credentials
.
getUserProfile
()==
null
)
{
return
Optional
.
empty
();
}
ExtendedUserProfile
profile
=
new
ExtendedUserProfile
(
credentials
.
getUserProfile
());
Set
<
RoleDefinition
>
mappedDefinitions
;
if
(
this
.
canMapRoles
(
profile
))
{
// Determine applicable role definitions
mappedDefinitions
=
this
.
getMappedRoles
(
profile
);
// Set applicable roles as Strings
profile
.
setRoles
(
mappedDefinitions
.
stream
()
.
map
(
mr
->
ROLE_PREFIX
+
mr
.
getRole
().
toUpperCase
())
.
collect
(
Collectors
.
toSet
()));
// Set maximum applicable level
profile
.
setLevel
(
mappedDefinitions
.
stream
()
.
mapToInt
(
RoleDefinition:
:
getLevel
)
.
max
().
orElse
(
0
));
}
return
Optional
.
ofNullable
(
profile
);
}
private
boolean
canMapRoles
(
ExtendedUserProfile
profile
)
{
return
clientName
!=
null
&&
profile
.
getExternalRoles
()!=
null
&&
!
profile
.
getExternalRoles
().
isEmpty
()
&&
roleDefinitions
!=
null
&&
!
roleDefinitions
.
isEmpty
();
}
}
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/authenticator/
User
ProfileCreator.java
→
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/authenticator/
Saml
ProfileCreator.java
View file @
fb0687c7
package
eu.dariah.de.dariahsp.authenticator
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Optional
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
org.pac4j.core.context.WebContext
;
import
org.pac4j.core.credentials.Credentials
;
import
org.pac4j.core.profile.UserProfile
;
import
org.pac4j.core.profile.creator.ProfileCreator
;
import
org.pac4j.saml.credentials.SAML2Credentials
;
import
eu.dariah.de.dariahsp.config.model.RoleDefinition
;
import
eu.dariah.de.dariahsp.model.ExtendedUserProfile
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
@Data
public
class
UserProfileCreator
<
C
extends
Credentials
>
implements
ProfileCreator
<
C
>
{
private
static
final
String
ROLE_PREFIX
=
"ROLE_"
;
private
final
String
clientName
;
private
List
<
RoleDefinition
>
roleDefinitions
;
@EqualsAndHashCode
(
callSuper
=
false
)
public
class
SamlProfileCreator
extends
BaseProfileCreator
implements
ProfileCreator
<
SAML2Credentials
>
{
public
SamlProfileCreator
(
String
clientName
)
{
super
(
clientName
);
}
@Override
public
Optional
<
UserProfile
>
create
(
final
C
credentials
,
final
WebContext
context
)
{
public
Optional
<
UserProfile
>
create
(
final
SAML2Credentials
credentials
,
final
WebContext
context
)
{
if
(
credentials
.
getUserProfile
()==
null
)
{
return
Optional
.
empty
();
}
ExtendedUserProfile
profile
=
new
ExtendedUserProfile
(
credentials
.
getUserProfile
());
Set
<
RoleDefinition
>
mappedDefinitions
;
if
(
this
.
canMapRoles
(
profile
))
{
// Determine applicable role definitions
...
...
@@ -38,7 +41,7 @@ public class UserProfileCreator<C extends Credentials> implements ProfileCreator
// Set maximum applicable level
profile
.
setLevel
(
mappedDefinitions
.
stream
()
.
mapToInt
(
RoleDefinition:
:
getLevel
)
.
max
().
orElse
(
0
));
.
max
().
orElse
(
0
));
}
return
Optional
.
ofNullable
(
profile
);
}
...
...
@@ -48,23 +51,4 @@ public class UserProfileCreator<C extends Credentials> implements ProfileCreator
profile
.
getExternalRoles
()!=
null
&&
!
profile
.
getExternalRoles
().
isEmpty
()
&&
roleDefinitions
!=
null
&&
!
roleDefinitions
.
isEmpty
();
}
private
Set
<
RoleDefinition
>
getMappedRoles
(
ExtendedUserProfile
profile
)
{
Set
<
RoleDefinition
>
roles
=
new
LinkedHashSet
<>();
for
(
RoleDefinition
rm
:
roleDefinitions
)
{
for
(
String
client
:
rm
.
getMappings
().
keySet
())
{
if
(!
client
.
equals
(
clientName
))
{
continue
;
}
for
(
String
extRole
:
profile
.
getExternalRoles
())
{
if
(!
extRole
.
trim
().
isEmpty
()
&&
rm
.
getMappings
().
get
(
client
).
contains
(
extRole
.
trim
())
&&
!
roles
.
contains
(
rm
))
{
roles
.
add
(
rm
);
}
}
}
}
return
roles
;
}
}
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/config/Attribute.java
View file @
fb0687c7
...
...
@@ -8,5 +8,6 @@ public class Attribute {
private
String
name
;
private
String
nameFormat
;
private
String
friendlyName
;
private
String
mappedAttribute
;
private
String
value
;
}
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/config/AttributeConfig.java
0 → 100644
View file @
fb0687c7
package
eu.dariah.de.dariahsp.config
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.beans.factory.annotation.Autowired
;
public
class
AttributeConfig
implements
InitializingBean
{
@Autowired
private
SecurityConfig
securityConfig
;
@Override
public
void
afterPropertiesSet
()
throws
Exception
{
if
(
securityConfig
.
getSaml
()==
null
||
!
securityConfig
.
getSaml
().
isEnabled
())
{
}
securityConfig
.
getSaml
().
getSp
().
getAttributeConfig
();
}
}
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/config/SamlProperties.java
View file @
fb0687c7
...
...
@@ -47,7 +47,7 @@ public class SamlProperties {
private
boolean
logoutRequestSigned
=
false
;
private
boolean
wantsAssertionsSigned
=
true
;
private
boolean
wantsResponsesSigned
=
true
;
private
List
<
ConditionalAttributeSet
>
requiredA
ttribute
s
;
private
List
<
ConditionalAttributeSet
>
a
ttribute
Config
;
// ------------------------------------------
...
...
@@ -62,7 +62,7 @@ public class SamlProperties {
return
p
;
}
public
int
getMaxAuthAge
()
{
return
maxAuthAge
<=
0
?
Integer
.
MAX_VALUE
:
maxAuthAge
;
return
maxAuthAge
<=
0
?
86400
:
maxAuthAge
;
// One day
}
public
HttpClient
getHttpClient
()
{
SAML2HttpClientBuilder
httpClient
=
new
SAML2HttpClientBuilder
();
...
...
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/config/SecurityConfig.java
View file @
fb0687c7
...
...
@@ -33,7 +33,8 @@ import org.springframework.security.access.vote.RoleHierarchyVoter;
import
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
;
import
eu.dariah.de.dariahsp.authenticator.LocalUsernamePasswordAuthenticator
;
import
eu.dariah.de.dariahsp.authenticator.UserProfileCreator
;
import
eu.dariah.de.dariahsp.authenticator.SamlProfileCreator
;
import
eu.dariah.de.dariahsp.authenticator.LocalProfileCreator
;
import
eu.dariah.de.dariahsp.config.model.RoleDefinition
;
import
eu.dariah.de.dariahsp.metadata.MetadataHelper
;
import
eu.dariah.de.dariahsp.web.AuthInfoHelper
;
...
...
@@ -54,9 +55,17 @@ public class SecurityConfig {
private
String
roleHierarchy
;
private
final
List
<
RoleDefinition
>
roleDefinitions
;
private
String
baseUrl
=
"http://localhost:8080"
;
private
String
defaultLoginUrl
=
baseUr
l
;
private
String
defaultLogoutUrl
=
baseUr
l
;
private
String
defaultLoginUrl
=
nul
l
;
private
String
defaultLogoutUrl
=
nul
l
;
public
String
getDefaultLoginUrl
()
{
return
defaultLoginUrl
==
null
?
baseUrl
:
defaultLoginUrl
;
}
public
String
getDefaultLogoutUrl
()
{
return
defaultLogoutUrl
==
null
?
baseUrl
:
defaultLogoutUrl
;
}
@Bean
AttributeConfig
attributeConfig
()
{
return
new
AttributeConfig
();
}
@Bean
public
Optional
<
LocalUsernamePasswordAuthenticator
>
localUsernamePasswordAuthenticator
()
{
if
(!
local
.
isEnabled
())
{
...
...
@@ -173,14 +182,14 @@ public class SecurityConfig {
}
private
User
ProfileCreator
<
SAML2Credentials
>
saml2ProfileCreator
()
{
User
ProfileCreator
<
SAML2Credentials
>
saml2ProfileCreator
=
new
User
ProfileCreator
<>
(
saml
.
getAuthorizerName
());
private
Saml
ProfileCreator
saml2ProfileCreator
()
{
Saml
ProfileCreator
saml2ProfileCreator
=
new
Saml
ProfileCreator
(
saml
.
getAuthorizerName
());
saml2ProfileCreator
.
setRoleDefinitions
(
roleDefinitions
);
return
saml2ProfileCreator
;
}
private
User
ProfileCreator
<
UsernamePasswordCredentials
>
localProfileCreator
()
{
User
ProfileCreator
<
UsernamePasswordCredentials
>
localProfileCreator
=
new
User
ProfileCreator
<>
(
local
.
getAuthorizerName
());
private
Local
ProfileCreator
localProfileCreator
()
{
Local
ProfileCreator
localProfileCreator
=
new
Local
ProfileCreator
(
local
.
getAuthorizerName
());
localProfileCreator
.
setRoleDefinitions
(
roleDefinitions
);
return
localProfileCreator
;
}
...
...
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/model/web/AuthPojo.java
View file @
fb0687c7
...
...
@@ -13,4 +13,5 @@ public class AuthPojo {
private
String
displayName
;
private
String
language
;
private
Set
<
String
>
roles
;
private
Set
<
String
>
externalRoles
;
}
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/web/AuthInfoHelper.java
View file @
fb0687c7
...
...
@@ -54,6 +54,7 @@ public class AuthInfoHelper {
pojo
.
setLevel
(
profile
.
getLevel
());
pojo
.
setUserId
(
profile
.
getId
());
pojo
.
setSessionId
(
this
.
getOrCreateSessionId
());
pojo
.
setExternalRoles
(
profile
.
getExternalRoles
());
}
return
pojo
;
}
...
...
dariahsp-core/src/main/resources/config.sample.yml
View file @
fb0687c7
# Config options of the dariahsp core library
# Commented properties reflect default values
auth
:
#baseUrl:
${baseUrl}
#baseUrl:
http://localhost:8080
#defaultLoginUrl: ${auth.baseUrl}
#defaultLogoutUrl: ${auth.baseUrl}
salt
:
Qmwp4CO7LDkOUDouAcCcUqd9ZGNbRG5Jyr5lpntOuB9
...
...
@@ -24,6 +24,7 @@ auth:
saml2
:
[
"
application_user"
]
local
:
enabled
:
true
authorizerName
:
local
# Same password for each user: 1234
users
:
-
username
:
'
admin'
...
...
@@ -37,6 +38,7 @@ auth:
roles
:
[
"
application_user"
]
saml
:
enabled
:
false
authorizerName
:
saml
keystore
:
path
:
/data/_srv/dariahsp/c105-229.cloud.gwdg.de.jks
pass
:
clariah
...
...
@@ -47,17 +49,17 @@ auth:
sp
:
#metadataResource: /data/_srv/dariahsp/sp_metadata.xml
maxAuthAge
:
-1
#entityId: ${
auth.saml.sp.
baseUrl}
#entityId: ${baseUrl}
signMetadata
:
true
#signingMethods: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
#digestMethods: http://www.w3.org/2001/04/xmlenc#sha256, http://www.w3.org/2001/04/xmlenc#sha512
#supportedProtocols: urn:oasis:names:tc:SAML:2.0:protocol
authnRequestSigned
:
true
authnRequestSigned
:
true
vv
logoutRequestSigned
:
true
wantsAssertionsSigned
:
true
wantsResponsesSigned
:
false
httpClientTimoutMs
:
2000
requiredA
ttribute
s
:
a
ttribute
Config
:
-
stage
:
ATTRIBUTES
required
:
true
attributeGroup
:
...
...
@@ -85,6 +87,7 @@ auth:
-
check
:
AND
attributes
:
-
friendlyName
:
eduPersonPrincipalName
mappedAttribute
:
id
name
:
urn:oid:1.3.6.1.4.1.5923.1.1.1.6
nameFormat
:
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
-
stage
:
AUTHENTICATION
...
...
@@ -96,5 +99,10 @@ auth:
name
:
urn:oid:0.9.2342.19200300.100.1.3
nameFormat
:
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
-
friendlyName
:
displayName
mappedAttribute
:
username
name
:
urn:oid:2.16.840.1.113730.3.1.241
nameFormat
:
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
-
friendlyName
:
isMemberOf
mappedAttribute
:
externalRoles
name
:
urn:oid:1.3.6.1.4.1.5923.1.5.1.1
nameFormat
:
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
\ No newline at end of file
dariahsp-sample-boot/src/main/resources/application.yml
View file @
fb0687c7
contextPath
:
/dme
baseUrl
:
http://localhost:8080${contextPath:/}
#baseUrl: http://localhost:8080${contextPath:/}
baseUrl
:
https://c105-229.cloud.gwdg.de${contextPath:/}
spring
:
mvc
:
...
...
@@ -35,6 +36,7 @@ auth:
saml2
:
[
"
application_user"
]
local
:
enabled
:
true
authorizerName
:
local
# Same password for each user: 1234
users
:
-
username
:
'
admin'
...
...
@@ -47,7 +49,8 @@ auth:
passhash
:
'
$2y$10$nmTcpRxs.RFUstkJJms6U.AW61Jmr64s9VNQLuhpU8gYrgzCapwka'
roles
:
[
"
application_user"
]
saml
:
enabled
:
false
enabled
:
true
authorizerName
:
SAML2Client
keystore
:
path
:
/data/_srv/dariahsp/c105-229.cloud.gwdg.de.jks
pass
:
clariah
...
...
@@ -58,7 +61,7 @@ auth:
sp
:
#metadataResource: /data/_srv/dariahsp/sp_metadata.xml
maxAuthAge
:
-1
#
entityId: ${
auth.saml.sp.
baseUrl}
entityId
:
${baseUrl}
signMetadata
:
true
#signingMethods: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
#digestMethods: http://www.w3.org/2001/04/xmlenc#sha256, http://www.w3.org/2001/04/xmlenc#sha512
...
...
@@ -68,7 +71,7 @@ auth:
wantsAssertionsSigned
:
true
wantsResponsesSigned
:
false
httpClientTimoutMs
:
2000
requiredA
ttribute
s
:
a
ttribute
Config
:
-
stage
:
ATTRIBUTES
required
:
true
attributeGroup
:
...
...
@@ -96,6 +99,7 @@ auth:
-
check
:
AND
attributes
:
-
friendlyName
:
eduPersonPrincipalName
mappedAttribute
:
id
name
:
urn:oid:1.3.6.1.4.1.5923.1.1.1.6
nameFormat
:
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
-
stage
:
AUTHENTICATION
...
...
@@ -107,5 +111,10 @@ auth:
name
:
urn:oid:0.9.2342.19200300.100.1.3
nameFormat
:
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
-
friendlyName
:
displayName
mappedAttribute
:
username
name
:
urn:oid:2.16.840.1.113730.3.1.241
nameFormat
:
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
-
friendlyName
:
isMemberOf
mappedAttribute
:
externalRoles
name
:
urn:oid:1.3.6.1.4.1.5923.1.5.1.1
nameFormat
:
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
\ No newline at end of file
dariahsp-sample-boot/src/main/webapp/WEB-INF/views/index.jsp
View file @
fb0687c7
...
...
@@ -33,12 +33,15 @@
<a
href=
"
<s:url
value=
"/protected/contributor"
/>
"
>
Protected url: CONTRIBUTOR role or higher required (security config)
</a><br
/>
<a
href=
"
<s:url
value=
"/protected/admin"
/>
"
>
Protected url: ADMINISTRATOR role required
</a><br
/>
<a
href=
"
<s:url
value=
"/blocked/noaccess"
/>
"
>
Blocked url: no access allowed
</a><br
/>
<br
/>
<h2>
SAML Metadata
</h2>
<a
href=
"
<s:url
value=
"/saml/metadata"
/>
"
>
SAML Metadata - best option: configured file before generation
</a><br
/>
<a
href=
"
<s:url
value=
"/saml/metadata/generate"
/>
"
>
SAML Metadata - generate based on configuration
</a><br
/>
<a
href=
"
<s:url
value=
"/saml/metadata/filesystem"
/>
"
>
SAML Metadata - force load from filesystem (fails if not existing)
</a><br
/>
<h2>
Login/Logout
</h2>
<a
href=
"
<s:url
value=
"/logout?url=/?forcepostlogouturl"
/>
"
>
logout
</a><br
/>
<a
href=
"
<s:url
value=
"/logout?url=/?forcepostlogouturl"
/>
"
>
pac4j local logout
</a><br
/>
<a
href=
"
<s:url
value=
"/centralLogout?url=/?forcepostlogouturlafteridp"
/>
"
>
pac4j central local logout
</a>
<a
href=
"
<s:url
value=
"/logout"
/>
"
>
local logout
</a><br
/>
<a
href=
"
<s:url
value=
"/centralLogout"
/>
"
>
central logout
</a>
<br
/>
<a
href=
"
<s:url
value=
"/forceLogin?client_name=saml"
/>
"
>
Force SAML login
</a>
(even if already authenticated)
<br
/>
<a
href=
"
<s:url
value=
"/forceLogin?client_name=local"
/>
"
>
Force local login
</a>
(even if already authenticated)
<br
/>
...
...
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