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
b75f9143
Commit
b75f9143
authored
Nov 20, 2020
by
Gradl, Tobias
Browse files
18: Adapt according to needs of first actual implementation (CR)
Task-Url:
#18
parent
e2f0564b
Pipeline
#17981
passed with stage
in 1 minute and 45 seconds
Changes
11
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/config/OrderedClient.java
0 → 100644
View file @
b75f9143
package
eu.dariah.de.dariahsp.config
;
import
org.pac4j.core.client.BaseClient
;
import
lombok.Data
;
@Data
public
class
OrderedClient
<
T
extends
BaseClient
<?>>
implements
Comparable
<
OrderedClient
<?>>
{
private
final
int
order
;
private
final
T
client
;
@Override
public
int
compareTo
(
OrderedClient
<?>
o
)
{
if
(
order
<
o
.
getOrder
())
{
return
-
1
;
}
else
if
(
order
==
o
.
getOrder
())
{
return
0
;
}
else
{
return
1
;
}
}
}
\ No newline at end of file
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/config/SecurityConfig.java
View file @
b75f9143
...
...
@@ -5,6 +5,7 @@ import java.net.URISyntaxException;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Optional
;
import
java.util.stream.Collectors
;
...
...
@@ -102,34 +103,34 @@ public class SecurityConfig {
}
@Bean
@SuppressWarnings
(
"rawtypes"
)
public
Config
config
(
Optional
<
ProfileActionHandler
>
profileActionHandler
)
throws
URISyntaxException
{
List
<
Client
>
clients
=
new
ArrayList
<>();
SAML2Client
samlClient
=
getSamlClient
();
FormClient
formClient
=
getFormClient
();
List
<
OrderedClient
<?>>
clients
=
new
ArrayList
<>();
OrderedClient
<
SAML2Client
>
samlClient
=
getSamlClient
();
OrderedClient
<
FormClient
>
formClient
=
getFormClient
();
if
(
samlClient
!=
null
)
{
clients
.
add
(
samlClient
);
}
if
(
formClient
!=
null
)
{
clients
.
add
(
formClient
);
}
Collections
.
sort
(
clients
);
Config
.
setProfileManagerFactory
(
"customizableProfileManager"
,
ctx
->
new
CustomizableProfileManager
(
ctx
,
profileActionHandler
.
orElse
(
null
)));
Config
c
=
new
Config
(
new
Clients
(
baseUrl
().
getAbsoluteUrl
(
"/callback"
),
clients
));
Config
conf
=
new
Config
(
new
Clients
(
baseUrl
().
getAbsoluteUrl
(
"/callback"
),
clients
.
stream
().
map
(
OrderedClient:
:
getClient
).
collect
(
Collectors
.
toList
())));
enabledClientNames
=
c
.
getClients
().
findAllClients
().
stream
()
enabledClientNames
=
c
onf
.
getClients
().
findAllClients
().
stream
()
.
map
(
Client:
:
getName
)
.
collect
(
Collectors
.
toList
());
return
c
;
return
c
onf
;
}
private
SAML2Client
getSamlClient
()
throws
URISyntaxException
{
private
OrderedClient
<
SAML2Client
>
getSamlClient
()
throws
URISyntaxException
{
if
(!
saml
.
isEnabled
())
{
return
null
;
}
final
SAML2Configuration
cfg
=
new
SAML2Configuration
();
// Keystore
...
...
@@ -175,17 +176,17 @@ public class SecurityConfig {
SAML2Client
c
=
new
SAML2Client
(
cfg
);
c
.
setName
(
saml
.
getAuthorizerName
());
c
.
setProfileCreator
(
saml2ProfileCreator
());
c
.
setAuthenticator
(
new
SAMLRequiredAttributeAuthenticator
(
cfg
.
getAttributeAsId
(),
cfg
.
getMappedAttributes
(),
saml
.
getSp
()));
return
c
;
c
.
setAuthenticator
(
new
SAMLRequiredAttributeAuthenticator
(
cfg
.
getAttributeAsId
(),
cfg
.
getMappedAttributes
(),
saml
.
getSp
()));
return
new
OrderedClient
<>(
saml
.
getOrder
(),
c
)
;
}
private
FormClient
getFormClient
()
throws
URISyntaxException
{
private
OrderedClient
<
FormClient
>
getFormClient
()
throws
URISyntaxException
{
Optional
<
LocalUsernamePasswordAuthenticator
>
localUsernamePasswordAuthenticator
=
localUsernamePasswordAuthenticator
();
if
(
localUsernamePasswordAuthenticator
.
isPresent
())
{
FormClient
c
=
new
FormClient
(
baseUrl
().
getAbsoluteUrl
(
"/login"
),
localUsernamePasswordAuthenticator
.
get
());
c
.
setName
(
local
.
getAuthorizerName
());
c
.
setProfileCreator
(
localProfileCreator
());
return
c
;
return
new
OrderedClient
<>(
local
.
getOrder
(),
c
)
;
}
return
null
;
}
...
...
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/config/local/LocalSecurity.java
View file @
b75f9143
...
...
@@ -6,5 +6,6 @@ import lombok.Data;
public
class
LocalSecurity
{
private
boolean
enabled
;
private
String
authorizerName
=
"local"
;
private
int
order
=
1
;
private
LocalUsers
[]
users
;
}
\ No newline at end of file
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/config/saml/SAMLSecurity.java
View file @
b75f9143
...
...
@@ -7,6 +7,7 @@ import lombok.Setter;
public
class
SAMLSecurity
{
private
boolean
enabled
;
private
String
authorizerName
=
"saml"
;
private
int
order
=
0
;
private
final
KeystoreProperties
keystore
=
new
KeystoreProperties
();
private
final
MetadataProperties
metadata
=
new
MetadataProperties
();
private
final
ServiceProvider
sp
=
new
ServiceProvider
();
...
...
dariahsp-core/src/main/java/eu/dariah/de/dariahsp/web/controller/CommonLoginController.java
0 → 100644
View file @
b75f9143
package
eu.dariah.de.dariahsp.web.controller
;
import
java.util.Map
;
import
org.pac4j.core.client.Client
;
import
org.pac4j.core.config.Config
;
import
org.pac4j.core.context.JEEContext
;
import
org.pac4j.core.exception.http.HttpAction
;
import
org.pac4j.core.exception.http.RedirectionActionHelper
;
import
org.pac4j.core.http.adapter.JEEHttpActionAdapter
;
import
org.pac4j.http.client.indirect.FormClient
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
eu.dariah.de.dariahsp.config.SecurityConfig
;
import
eu.dariah.de.dariahsp.error.AuthenticatorNotAvailable
;
import
eu.dariah.de.dariahsp.web.AuthInfoHelper
;
@Controller
public
class
CommonLoginController
{
@Autowired
protected
AuthInfoHelper
authInfoHelper
;
@Autowired
private
SecurityConfig
securityConfig
;
@Autowired
private
Config
config
;
@Autowired
private
JEEContext
jeeContext
;
/**
* Present the local login form; override if the desired view is not 'login'
*
* @param map
* @param requestUrl
* @return login view
*/
@RequestMapping
(
"/login"
)
public
String
loginForm
(
Map
<
String
,
Object
>
map
,
@RequestParam
(
value
=
"url"
,
required
=
false
)
String
requestUrl
)
{
final
FormClient
formClient
=
(
FormClient
)
config
.
getClients
().
findClient
(
securityConfig
.
getLocal
().
getAuthorizerName
()).
orElseThrow
();
map
.
put
(
"callbackUrl"
,
formClient
.
getCallbackUrl
());
map
.
put
(
"requestUrl"
,
requestUrl
);
return
"login"
;
}
/**
* Mapping that requires authentication and thus redirects to configured client[0] if a user is not authenticated
* A provided callbackUrl is used for redirecting a user to a specified URL post-login.
*
* @param requestUrl
* @return redirection
*/
@PreAuthorize
(
"isAuthenticated()"
)
@RequestMapping
(
"/filteredLogin"
)
@ResponseBody
public
String
filteredLogin
(
@RequestParam
(
value
=
"url"
,
required
=
false
)
String
requestUrl
)
{
HttpAction
action
;
try
{
action
=
RedirectionActionHelper
.
buildRedirectUrlAction
(
jeeContext
,
requestUrl
!=
null
?
requestUrl
:
securityConfig
.
getDefaultLoginUrl
());
}
catch
(
final
HttpAction
e
)
{
action
=
e
;
}
JEEHttpActionAdapter
.
INSTANCE
.
adapt
(
action
,
jeeContext
);
return
null
;
}
/**
* Initiate a login based on a requested authentication client specified in terms of a client_name GET parameter
*
* @param client_name name of the authentication client
* @return redirection
*/
@RequestMapping
(
"/loginClient"
)
@ResponseBody
public
String
forceLogin
()
{
final
String
clientName
=
authInfoHelper
.
getRequestedClientName
();
final
Client
<?>
client
=
config
.
getClients
().
findClient
(
clientName
).
orElse
(
null
);
if
(
client
==
null
)
{
throw
new
AuthenticatorNotAvailable
(
clientName
);
}
HttpAction
action
;
try
{
action
=
client
.
getRedirectionAction
(
jeeContext
).
orElseThrow
(()
->
new
AuthenticatorNotAvailable
(
clientName
));
}
catch
(
final
HttpAction
e
)
{
action
=
e
;
}
JEEHttpActionAdapter
.
INSTANCE
.
adapt
(
action
,
jeeContext
);
return
null
;
}
}
dariahsp-core/src/main/resources/config.sample.yml
View file @
b75f9143
...
...
@@ -33,6 +33,8 @@ auth:
local
:
[
"
application_user"
]
saml
:
[
"
application_user"
]
local
:
# The client with the lowest number here is used when selecting a default authenticator
order
:
0
# Enable local authentication
enabled
:
true
# Name of the method
...
...
@@ -52,6 +54,7 @@ auth:
passhash
:
'
$2y$10$nmTcpRxs.RFUstkJJms6U.AW61Jmr64s9VNQLuhpU8gYrgzCapwka'
roles
:
[
"
application_user"
]
saml
:
order
:
1
# Enable SAML authentication
enabled
:
false
# Name of the method
...
...
dariahsp-sample-boot/src/main/java/eu/dariah/de/dariahsp/sample/config/SampleConfig.java
View file @
b75f9143
...
...
@@ -11,6 +11,7 @@ import org.springframework.context.annotation.Configuration;
import
eu.dariah.de.dariahsp.CustomizableProfileManager
;
import
eu.dariah.de.dariahsp.ProfileActionHandler
;
import
eu.dariah.de.dariahsp.sample.profiles.SampleProfileActionHandler
;
import
eu.dariah.de.dariahsp.web.controller.CommonLoginController
;
import
eu.dariah.de.dariahsp.web.controller.SAMLMetadataController
;
@Configuration
...
...
@@ -57,4 +58,14 @@ public class SampleConfig {
public
SAMLMetadataController
samlMetadataController
()
{
return
new
SAMLMetadataController
();
}
/**
* Controller that binds to common login mappings
*
* @return LoginLogoutController bean
*/
@Bean
public
CommonLoginController
loginLogoutController
()
{
return
new
CommonLoginController
();
}
}
dariahsp-sample-boot/src/main/java/eu/dariah/de/dariahsp/sample/controller/SampleController.java
View file @
b75f9143
...
...
@@ -2,23 +2,13 @@ package eu.dariah.de.dariahsp.sample.controller;
import
java.util.Map
;
import
org.pac4j.core.client.Client
;
import
org.pac4j.core.config.Config
;
import
org.pac4j.core.context.JEEContext
;
import
org.pac4j.core.exception.http.HttpAction
;
import
org.pac4j.core.http.adapter.JEEHttpActionAdapter
;
import
org.pac4j.http.client.indirect.FormClient
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.access.annotation.Secured
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
eu.dariah.de.dariahsp.config.SecurityConfig
;
import
eu.dariah.de.dariahsp.error.AuthenticatorNotAvailable
;
import
eu.dariah.de.dariahsp.web.AuthInfoHelper
;
/**
* Main controller of the sample application. All views are handled in the index JSP.
...
...
@@ -32,11 +22,7 @@ public class SampleController {
private
static
String
INDEX_PAGE
=
"index"
;
@Autowired
private
SecurityConfig
securityConfig
;
@Autowired
private
Config
config
;
@Autowired
private
JEEContext
jeeContext
;
@Autowired
private
AuthInfoHelper
authInfoHelper
;
@GetMapping
(
"/"
)
public
String
home
(
Map
<
String
,
Object
>
map
)
{
this
.
assembleMap
(
map
,
...
...
@@ -94,33 +80,7 @@ public class SampleController {
"No access at all"
);
return
INDEX_PAGE
;
}
@RequestMapping
(
"/login"
)
public
String
loginForm
(
Map
<
String
,
Object
>
map
)
{
final
FormClient
formClient
=
(
FormClient
)
config
.
getClients
().
findClient
(
securityConfig
.
getLocal
().
getAuthorizerName
()).
get
();
map
.
put
(
"callbackUrl"
,
formClient
.
getCallbackUrl
());
return
"login"
;
}
@RequestMapping
(
"/forceLogin"
)
@ResponseBody
public
String
forceLogin
()
{
final
String
clientName
=
authInfoHelper
.
getRequestedClientName
();
final
Client
<?>
client
=
config
.
getClients
().
findClient
(
clientName
).
orElse
(
null
);
if
(
client
==
null
)
{
throw
new
AuthenticatorNotAvailable
(
clientName
);
}
HttpAction
action
;
try
{
action
=
client
.
getRedirectionAction
(
jeeContext
).
orElseThrow
(()
->
new
AuthenticatorNotAvailable
(
clientName
));
}
catch
(
final
HttpAction
e
)
{
action
=
e
;
}
JEEHttpActionAdapter
.
INSTANCE
.
adapt
(
action
,
jeeContext
);
return
null
;
}
private
void
assembleMap
(
Map
<
String
,
Object
>
map
,
String
page
,
String
restrictions
)
{
// _auth and _sessionId are inserted by the AuthInfoHandlerInterceptor
map
.
put
(
"requestedPage"
,
page
);
...
...
dariahsp-sample-boot/src/main/resources/application.yml
View file @
b75f9143
#contextPath: /
contextpath
#baseUrl: https://
externally.visible.example.com
${contextPath:/}
#contextPath: /
dme
#baseUrl: https://
c105-229.cloud.gwdg.de
${contextPath:/}
baseUrl
:
http://localhost:8080
spring
:
...
...
@@ -35,6 +35,7 @@ auth:
local
:
[
"
application_user"
]
saml
:
[
"
application_user"
]
local
:
order
:
0
enabled
:
true
authorizerName
:
local
# Same password for each user: 1234
...
...
@@ -49,7 +50,8 @@ auth:
passhash
:
'
$2y$10$nmTcpRxs.RFUstkJJms6U.AW61Jmr64s9VNQLuhpU8gYrgzCapwka'
roles
:
[
"
application_user"
]
saml
:
enabled
:
false
order
:
1
enabled
:
true
authorizerName
:
saml
keystore
:
#path: /path/to/keystore.jks
...
...
dariahsp-sample-boot/src/main/webapp/WEB-INF/views/index.jsp
View file @
b75f9143
...
...
@@ -28,7 +28,7 @@
<b>
SAML enabled
</b>
: ${samlEnabled}
<h2>
Pages
</h2>
<a
href=
"
<s:url
value=
"/"
/>
"
>
Unprotected base url
</a><br
/>
<a
href=
"
<s:url
value=
"/protected/authenticated"
/>
"
>
Protected url: authentication required
</a><br
/>
<a
href=
"
<s:url
value=
"/protected/authenticated"
var=
"protectedAuthenticated"
/>
"
>
Protected url: authentication required
</a><br
/>
<a
href=
"
<s:url
value=
"/method/authenticated"
/>
"
>
Protected url: authentication required (method annotation)
</a><br
/>
<a
href=
"
<s:url
value=
"/method/contributor"
/>
"
>
Protected url: CONTRIBUTOR role or higher required (method annotation)
</a><br
/>
<a
href=
"
<s:url
value=
"/protected/contributor"
/>
"
>
Protected url: CONTRIBUTOR role or higher required (security config)
</a><br
/>
...
...
@@ -44,8 +44,10 @@
<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
/>
<a
href=
"
<s:url
value=
"/login?url=${protectedAuthenticated}"
/>
"
>
Enter local login form
</a>
(with callbackUrl)
<br
/>
<a
href=
"
<s:url
value=
"/filteredLogin?url=${protectedAuthenticated}"
/>
"
>
Enter filtered login
</a>
(with callbackUrl)
<br
/>
<a
href=
"
<s:url
value=
"/loginClient?client_name=saml"
/>
"
>
Force SAML login
</a>
(even if already authenticated)
<br
/>
<a
href=
"
<s:url
value=
"/loginClient?client_name=local"
/>
"
>
Force local login
</a>
(even if already authenticated)
<br
/>
<br
/><br
/>
</body>
</html>
\ No newline at end of file
dariahsp-sample-boot/src/main/webapp/WEB-INF/views/login.jsp
View file @
b75f9143
<%@ page
language=
"java"
contentType=
"text/html; charset=UTF-8"
pageEncoding=
"UTF-8"
%>
<%@ taglib
prefix=
"s"
uri=
"http://www.springframework.org/tags"
%>
<!DOCTYPE HTML>
<html>
<head>
...
...
@@ -7,7 +9,7 @@
<body>
<h1>
Local login
</h1>
<p>
Default accounts
<em>
admin
</em>
,
<em>
contributor
</em>
,
<em>
user
</em>
(each with password
<em>
1234
</em>
)
</p>
<form
action=
"${callbackUrl}?client_name=local"
method=
"POST"
>
<form
action=
"${callbackUrl}?client_name=local
&url=${requestUrl}
"
method=
"POST"
>
<input
type=
"text"
name=
"username"
value=
""
/>
<p
/>
<input
type=
"password"
name=
"password"
value=
""
/>
...
...
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