diff --git a/src/main/java/de/thm/arsnova/config/SecurityConfig.java b/src/main/java/de/thm/arsnova/config/SecurityConfig.java index e4b16462f5fa82112ea9dfcac1999dbf06f07e3f..41897f22b5132c3f45e71319b61503c44b7666c2 100644 --- a/src/main/java/de/thm/arsnova/config/SecurityConfig.java +++ b/src/main/java/de/thm/arsnova/config/SecurityConfig.java @@ -33,6 +33,7 @@ import org.pac4j.core.config.Config; import org.pac4j.oauth.client.FacebookClient; import org.pac4j.oauth.client.TwitterClient; import org.pac4j.oidc.client.GoogleOidcClient; +import org.pac4j.oidc.client.OidcClient; import org.pac4j.oidc.config.OidcConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -97,6 +98,7 @@ import java.util.List; @Profile("!test") public class SecurityConfig extends WebSecurityConfigurerAdapter { public static final String OAUTH_CALLBACK_PATH_SUFFIX = "/auth/oauth_callback"; + private static final String OIDC_DISCOVERY_PATH_SUFFIX = "/.well-known/openid-configuration"; public static final String CAS_LOGIN_PATH_SUFFIX = "/auth/login/cas"; public static final String CAS_LOGOUT_PATH_SUFFIX = "/auth/logout/cas"; public static final String RUN_AS_KEY_PREFIX = "RUN_AS_KEY"; @@ -122,6 +124,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Value("${security.cas.enabled}") private boolean casEnabled; @Value("${security.cas-server-url}") private String casUrl; + @Value("${security.oidc.enabled}") private boolean oidcEnabled; + @Value("${security.oidc.issuer}") private String oidcIssuer; + @Value("${security.oidc.client-id}") private String oidcClientId; + @Value("${security.oidc.secret}") private String oidcSecret; + @Value("${security.facebook.enabled}") private boolean facebookEnabled; @Value("${security.facebook.key}") private String facebookKey; @Value("${security.facebook.secret}") private String facebookSecret; @@ -147,7 +154,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { http.addFilter(casLogoutFilter()); } - if (facebookEnabled || googleEnabled || twitterEnabled) { + if (oidcEnabled || facebookEnabled || googleEnabled || twitterEnabled) { http.addFilterAfter(oauthCallbackFilter(), CasAuthenticationFilter.class); } } @@ -214,6 +221,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { providers.add("user-db"); auth.authenticationProvider(daoAuthenticationProvider()); } + if (oidcEnabled) { + providers.add("oidc"); + } if (googleEnabled || facebookEnabled || twitterEnabled) { if (googleEnabled) { providers.add("google"); @@ -430,6 +440,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public Config oauthConfig() { List<Client> clients = new ArrayList<>(); + if (oidcEnabled) { + clients.add(oidcClient()); + } if (facebookEnabled) { clients.add(facebookClient()); } @@ -457,6 +470,19 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { return new OauthAuthenticationProvider(); } + @Bean + public OidcClient oidcClient() { + OidcConfiguration config = new OidcConfiguration(); + config.setDiscoveryURI(oidcIssuer + OIDC_DISCOVERY_PATH_SUFFIX); + config.setClientId(oidcClientId); + config.setSecret(oidcSecret); + config.setScope("openid"); + OidcClient client = new OidcClient(config); + client.setCallbackUrl(rootUrl + apiPath + OAUTH_CALLBACK_PATH_SUFFIX + "?client_name=OidcClient"); + + return client; + } + @Bean public FacebookClient facebookClient() { final FacebookClient client = new FacebookClient(facebookKey, facebookSecret); diff --git a/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java b/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java index 12c7a0c74dc5f1fb4a3b9f06d35eadfbfa9b2f02..aecc1651b0cfd5024830ecb5be4fb0890a56eb45 100644 --- a/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java +++ b/src/main/java/de/thm/arsnova/controller/v2/AuthenticationController.java @@ -30,6 +30,7 @@ import org.pac4j.core.exception.HttpAction; import org.pac4j.oauth.client.FacebookClient; import org.pac4j.oauth.client.TwitterClient; import org.pac4j.oidc.client.GoogleOidcClient; +import org.pac4j.oidc.client.OidcClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -104,6 +105,12 @@ public class AuthenticationController extends AbstractController { @Value("${security.cas.image:}") private String casImage; @Value("${security.cas.order}") private int casOrder; + @Value("${security.oidc.enabled}") private boolean oidcEnabled; + @Value("${security.oidc.allowed-roles:speaker,student}") private String[] oidcRoles; + @Value("${security.oidc.title:OIDC}") private String oidcTitle; + @Value("${security.oidc.image:}") private String oidcImage; + @Value("${security.oidc.order}") private int oidcOrder; + @Value("${security.facebook.enabled}") private boolean facebookEnabled; @Value("${security.facebook.allowed-roles:speaker,student}") private String[] facebookRoles; @Value("${security.facebook.order}") private int facebookOrder; @@ -119,6 +126,9 @@ public class AuthenticationController extends AbstractController { @Autowired private ServletContext servletContext; + @Autowired(required = false) + private OidcClient oidcClient; + @Autowired(required = false) private TwitterClient twitterClient; @@ -229,6 +239,9 @@ public class AuthenticationController extends AbstractController { if (casEnabled && "cas".equals(type)) { casEntryPoint.commence(request, response, null); + } else if (oidcEnabled && "oidc".equals(type)) { + result = new RedirectView( + oidcClient.getRedirectAction(new J2EContext(request, response)).getLocation()); } else if (twitterEnabled && "twitter".equals(type)) { result = new RedirectView( twitterClient.getRedirectAction(new J2EContext(request, response)).getLocation()); @@ -334,6 +347,17 @@ public class AuthenticationController extends AbstractController { services.add(sdesc); } + if (oidcEnabled) { + ServiceDescription sdesc = new ServiceDescription( + "oidc", + oidcTitle, + MessageFormat.format(dialogUrl, "oidc"), + oidcRoles + ); + sdesc.setOrder(oidcOrder); + services.add(sdesc); + } + if (facebookEnabled) { ServiceDescription sdesc = new ServiceDescription( "facebook", diff --git a/src/main/resources/arsnova.properties.example b/src/main/resources/arsnova.properties.example index 27a57e95c43d8952319f5eedb537dd65979a33c1..a62fbddccd98d60481113df741db64c582964f0b 100644 --- a/src/main/resources/arsnova.properties.example +++ b/src/main/resources/arsnova.properties.example @@ -149,6 +149,17 @@ security.cas.image= security.cas.order=0 security.cas-server-url=https://example.com/cas +# OpenID Connect authentication +# +security.oidc.enabled=false +security.oidc.allowed-roles=speaker,student +security.oidc.title=OIDC +security.oidc.image= +security.oidc.order=0 +security.oidc.issuer=https://example.com/oidc +security.oidc.client-id= +security.oidc.secret= + # OAuth authentication with third party services # Specific parameters: # key: OAuth key/id provided by a third party auth service diff --git a/src/test/resources/arsnova.properties.example b/src/test/resources/arsnova.properties.example index 27a57e95c43d8952319f5eedb537dd65979a33c1..a62fbddccd98d60481113df741db64c582964f0b 100644 --- a/src/test/resources/arsnova.properties.example +++ b/src/test/resources/arsnova.properties.example @@ -149,6 +149,17 @@ security.cas.image= security.cas.order=0 security.cas-server-url=https://example.com/cas +# OpenID Connect authentication +# +security.oidc.enabled=false +security.oidc.allowed-roles=speaker,student +security.oidc.title=OIDC +security.oidc.image= +security.oidc.order=0 +security.oidc.issuer=https://example.com/oidc +security.oidc.client-id= +security.oidc.secret= + # OAuth authentication with third party services # Specific parameters: # key: OAuth key/id provided by a third party auth service