Skip to content

Commit

Permalink
Adding SSO
Browse files Browse the repository at this point in the history
  • Loading branch information
rnavagamuwa committed Mar 29, 2019
1 parent 2a8f10b commit 7002a80
Show file tree
Hide file tree
Showing 40 changed files with 1,308 additions and 238 deletions.
39 changes: 38 additions & 1 deletion sample/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,53 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.security.extensions</groupId>
<artifactId>spring-security-saml2-core</artifactId>
<version>1.0.9.RELEASE</version>
<exclusions>
<exclusion>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.opensaml</groupId>
<artifactId>opensaml</artifactId>
<version>2.6.4</version>
<exclusions>
<exclusion>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</exclusion>
</exclusions>
</dependency>


<dependency>
<groupId>org.wso2.spring.security</groupId>
<artifactId>abac</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</exclusion>
</exclusions>
</dependency>

</dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2019 Vincenzo De Notaris
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.rnavagamuwa.springsecurity;

import com.rnavagamuwa.springsecurity.stereotypes.CurrentUser;
import org.springframework.core.MethodParameter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.security.Principal;

@Component
public class CurrentUserHandlerMethodArgumentResolver implements
HandlerMethodArgumentResolver {

public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.getParameterAnnotation(CurrentUser.class) != null
&& methodParameter.getParameterType().equals(User.class);
}

public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
if (this.supportsParameter(methodParameter)) {
Principal principal = (Principal) webRequest.getUserPrincipal();
return (User) ((Authentication) principal).getPrincipal();
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2019 Vincenzo De Notaris
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.rnavagamuwa.springsecurity;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.saml.SAMLCredential;
import org.springframework.security.saml.userdetails.SAMLUserDetailsService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService {

// Logger
private static final Logger LOG = LoggerFactory.getLogger(SAMLUserDetailsServiceImpl.class);

public Object loadUserBySAML(SAMLCredential credential)
throws UsernameNotFoundException {

// The method is supposed to identify local account of user referenced by
// data in the SAML assertion and return UserDetails object describing the user.

String userID = credential.getNameID().getValue();

LOG.info(userID + " is logged in");
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
authorities.add(authority);

// In a real scenario, this implementation has to locate user in a arbitrary
// dataStore based on information present in the SAMLCredential and
// returns such a date in a form of application specific UserDetails object.
return new User(userID, "password", true, true, true, true, authorities);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.rnavagamuwa.springsecurity.controller;

import com.rnavagamuwa.springsecurity.stereotypes.CurrentUser;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

@RequestMapping("/hello")
public String helloWorld(@CurrentUser User user, Model model) {

model.addAttribute("username", user.getUsername());
return "pages/hello";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2019 Vincenzo De Notaris
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.rnavagamuwa.springsecurity.controller;

import com.rnavagamuwa.springsecurity.stereotypes.CurrentUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class LandingController {

// Logger
private static final Logger LOG = LoggerFactory
.getLogger(LandingController.class);

@RequestMapping("/landing")
public String landing(@CurrentUser User user, Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null)
LOG.debug("Current authentication instance from security context is null");
else
LOG.debug("Current authentication instance from security context: "
+ this.getClass().getSimpleName());
model.addAttribute("username", user.getUsername());
return "pages/landing";
}

@RequestMapping("/")
public String root() {

return "redirect:/landing";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2019 Vincenzo De Notaris
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.rnavagamuwa.springsecurity.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.saml.metadata.MetadataManager;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import java.util.Set;

@Controller
@RequestMapping("/saml")
public class SSOController {

// Logger
private static final Logger LOG = LoggerFactory
.getLogger(SSOController.class);

@Autowired
private MetadataManager metadata;

@RequestMapping(value = "/discovery", method = RequestMethod.GET)
public String idpSelection(HttpServletRequest request, Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null)
LOG.debug("Current authentication instance from security context is null");
else
LOG.debug("Current authentication instance from security context: "
+ this.getClass().getSimpleName());
if (auth == null || (auth instanceof AnonymousAuthenticationToken)) {
Set<String> idps = metadata.getIDPEntityNames();
for (String idp : idps)
LOG.info("Configured Identity Provider for SSO: " + idp);
model.addAttribute("idps", idps);
return "pages/discovery";
} else {
LOG.warn("The current user is already logged.");
return "redirect:/landing";
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.rnavagamuwa.springsecurity.controller.rest;

import com.rnavagamuwa.springsecurity.stereotypes.CurrentUser;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class AuthController {

@RequestMapping("/auth")
@PreAuthorize("hasPermission('admin_xacml','{actionid:action-id,resourceid:resource-id}')")
public ResponseEntity sampleAuth(@CurrentUser User user, Model model) {

return new ResponseEntity<>("Successfully authorized", HttpStatus.OK);
}
}

This file was deleted.

Loading

0 comments on commit 7002a80

Please sign in to comment.