what is recommended way to create custom pages OAuth Approval page:
I have to completely override the stuff on the page, need to add styles, branding etc. What is the right way to achieve that? Where could I see the source of the default page to use it as a starting point?
I also need to override the /login page but I think the approach of overriding it is going to be pretty much the same.
The recommended way is to provide a normal Spring MVC #RequestMapping for the "/oauth/confirm_access". You can look at WhitelabelApprovalEndpoint for the default implementation. Don't forget to use #SessionAttributes("authorizationRequest") in your controller.
In addition to #DaveSyer's answer, which should work for the most of the cases. Sometimes based on configuration and customization the aforementioned method may not work, if FrameworkEndpointHandlerMapping from Spring Security OAuth package has higher order than RequestMappingHandlerMapping of your application. If this is the case, then servlet dispatcher will never reach you mapping and will always show the default page.
One way to fix it is to change the order of mappers, given that FrameworkEndpointHandlerMapping's order is Order.LOWEST_PRECEDENCE - 2.
Another way is to set the approval page to a custom URL, not mapped by FrameworkEndpointHandlerMapping, thus servlet dispatcher will reaches you application's mapping
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthorizationEndpoint authorizationEndpoint;
#PostConstruct
public void init() {
authorizationEndpoint.setUserApprovalPage("forward:/oauth/custom_confirm_access");
authorizationEndpoint.setErrorPage("forward:/oauth/custom_error");
}
}
With such a configuration mappings of /oauth/custom_confirm_access and /oauth/custom_error will be used as a confirmation page and an error page respectively.
Related
In my project I use Spring-Data, Spring-Data-Rest and Spring-Security.
What I need to accomplish is to implement domain object security (ACL) over these repositories. Specificaly #PostFilter over Pageable.findAll() method.
Method level security is easily implemented as outlined here.
There is also a section in docs about using security expression with #Query here.
But although I can use hasPermission(..) method inside #Query too, there is no way to include the object (SQL row) in this method - to be specific do this:
#Query("select u from #{#entityName} u where 1 = ?#{security.hasPermission(u, 'read') ? 1 : 0}")
Now I understand that this is way different than modifying the query pre-execution like this:
#Query("select m from Message m where m.to.id = ?#{ principal?.id }")
I also found the following jira issue:
https://jira.spring.io/browse/DATACMNS-293
Which I suspect that once it gets resolved there will be a solution to this, but it doesn't seem like it's going to be anytime soon.
I still need to implement this functionality and for that I would like to get your input and pointers on possible solutions.
Right now I am thinking about creating my custom annotation that will mimmick the #PostFilter one and use the same syntax but will get invoked manually inside my own BaseRepositoryImplementation. There I will get the repository interface from type and Repositories#getRepositoryInformationFor(type)#getRepositoryInterface(), find the annotation on respective method and manually invoke the security check.
Do you maybe have a different solution, or some notes about my proposed solution?
Also do you happen to know if there is any timetable on the mentioned jira issue?
One lightweight way is to do it is using the hasPermission() method and implementing your own "Permission Evaluator" at the Controller level, if that's an option for you.
#PreAuthorize("hasPermission(#employee, 'edit')")
public void editEmployee(Employee employee) {
...
}
#Component
public class PermissionEvaluatorImpl implements PermissionEvaluator {
#Override
public boolean hasPermission(Authentication auth,
Object targetDomainObject, Object permission) {
// return true if "auth" has "permission" permission for the user.
// Current-user can be obtained from auth.
}
...
}
This is described in more detail here: http://www.naturalprogrammer.com/spring-domain-object-security-logged-in-user/
The configuration method below doesn't get fired.
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(SCM.Web.Startup))]
namespace SCM.Web
{
public partial class Startup
{
public void Configuration(IAppBuilder builder) { }
}
}
I've followed all the hints from here and it's a new project, not an upgrade. I can't for my life see how to get it to stop on the breakpoint and I'm in need to get more suggestions on how to troubleshoot it.
It's an intranet application so there's no logging in. The identity gets set to the Windows credentials, instead. I need to assign the roles so that only certain users can access certain actions in the controllers. I'm usually applying OWIN and application cookies, so that's the method I'm trying to follow here, as well.
You need an OwinStartup attribute to tell Owin what method to call. From the docs:
Used to mark which class in an assembly should be used for automatic startup.
Add one to your project, before the namespace declaration:
[assembly: OwinStartup(typeof(Your.Namespace.Startup))]
namespace Your.Namespace
{
public partial class Startup
{
public void Configuration(IAppBuilder builder) { }
}
}
There are some other methods to let Owin know which method (described here) but this is the simplest and probably the most common.
If you are running the website on an external IIS or maybe on the "real" IIS installed on your computer (and not the one that is fired up when you start the run), then it's likely that you're missing the breakpoint because the debugger isn't attached to the process yet when you pass by.
I think that you can confirm it by either checking the settings of your solution and projects or simply adding this code to the method that you don't think that you pass through.
throw new Exception("Killroy was here...");
I've been having all sorts of giggles configuring some custom filters in the spring security filter chain. The primary problem surrounds a custom AbstractAuthenticationProcessingFilter. This filter requires the AuthenticationManager as well as the SessionAuthenticationStrategy. Using the adapter:
#Override
protected void configure(HttpSecurity http) throws Exception {
....
AbstractAuthenticationProcessingFilter processingFilter = new MyAuthenticationProcessingFilter();
processingFilter.setAuthenticationManager(authenticationManager());
processingFilter.setSessionAuthenticationStrategy(http.getSharedObject(SessionFixationProtectionStrategy.class));
http.addFilterBefore(processingFilter, UsernamePasswordAuthenticationFilter.class);
First, I had problems with the authenticationManager() returning null. Tracing that down showed that during the creation/initialization of the adapter and specifically the WebSecurity.init() method invoking getHttp(), this code ultimately calls AuthenticationManagerBuilder.build() which returns null at performBuild()
if(!isConfigured()) {
logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
return null;
}
Sadly, this then flags the AuthenticationManager as initialized (to null) and forever returns the wrong result.. all this before it even gets to my adapter code! I finally figured out I could use authenticationManagerBean() instead.
But I also need to set the sessionAuthenticationStrategy. Sadly, this is also null at this time. I've noticed the 'standard' filters all use a 'Configurer' to set them up, and apparently by this time, all the beans are correctly defined. But I haven't figured out how to register my 'configurer' instead of my filter directly.
So.. how does one build a custom AuthenticationProcessingFilter with the required attributes defined within a java configuration adapter?
Well, I figured out how to setup a configurer for my custom filter. HttpSecurity.apply() takes a configurer and you can invoke that during the WebSecurityConfigurerAdapter.configure(http) method. Turns out trying to set up filters at that time is probably a bad idea.. at least filters that depend on other portions of the security infrastructure.
Inside your configurer, create and add a security filter using init(http) and configure(http). By the time the configurers are invoked, many shared objects have been defined and inserted into http, things such as the AuthenticationManager and the SessionAuthenticationStrategy instances.
I am using spring security plugin in my Grails project. In order to secure the URLs, I am using interceptUrlMap.
My User and Role classes are User.groovy and Role.groovy respectively. Based on these classes, the s2-quickstart script has generated the UserController.groovy and RoleController.groovy
The problem arises when I want to secure UserController.groovy. My requirement is that I cannot permit all users to create a new user. Therefore certain actions of the UserController need to be blocked for users with the proper role privileges.
However no matter how I try to restrict access, I see that all the actions of UserController are always accessible.
Could anyone please explain where I am going wrong. Any help is highly appreciated.
Better use annotations instead of defining rules in Config.groovy. That helps in two ways i.e. first, hot reloading will always work and second you can override any rule easily in Config.groovy. That means you can use both annotation and plain rules in Config.groovy.
So change this in Config.groovy
grails.plugin.springsecurity.securityConfigType = "Annotation"
and start protecting your controller or actions like:
import grails.plugin.springsecurity.annotation.Secured
#Secured(["ROLE_MRU"])
class UserController {
def edit() {
// action code
}
#Secured(["ROLE_ADMIN"])
def show() {
// action code
}
}
I have managed to solve the issue. The problem was that I was editing Config.groovy while the application was still running. Hot deployment was not taking place.
Once I restarted the application, the functionality started working.
Thanks for all the help.
I'm developing an app based on Grails and Vaadin 7. I managed to make them work with SpringSecurity for authentication and authorization, but I had to develop my own Service that calls the Spring Security authentication manager to make it work with Vaadin:
class SecurityService {
static transactional = true
def springSecurityService
def authenticationManager
void signIn(String username, String password) {
try {
def authentication = new UsernamePasswordAuthenticationToken(username, password)
SCH.context.authentication = authenticationManager.authenticate(authentication)
} catch (BadCredentialsException e) {
throw new SecurityException("Invalid username/password")
}
}
}
The problem is that now I need to implement a remember me authentication and I don't know from where to start.
How do I make the authenticationManager know that I want it to use remeberMeAuthentication? I can get a boolean value from a checkbox on the login View, but what do I do with it next?
Since your question is specific to the handling of checkbox value (remember me flag) coming from login page, the answer is that you have to call loginSuccess or loginFail method of RememberMeServices. The loginSuccess adds auto-login cookie in the response and loginFail removes that cookie.
But I guess above answer won't help you much unless you are sure that you have RememberMeServices configured in your app. Maybe following steps that configure RememberMeServices will help you do whole thing your way (or help you understand the out of the box functionality):
(1) Create a class (call it myRememberMeServices) that implements RememberMeServices and LogoutHandler.
(2) In autoLogin method, create an authentication object (UsernamePasswordAuthenticationToken) after parsing the cookie value.
(3) In loginFail method, cancel the cookie.
(4) In loginSuccess method, create an auto-login cookie. Add value that you would use in autoLogin method. Usually cookie value is encrypted.
(5) In logout method , cancel the cookie.
(6) Inject myRememberMeServices in following four places and call appropriate method:
(a) At the time of successful login (if checkbox value is set),
(b) At the time of failed login,
(c) On logout, and
(d) In filter that does autologin
It is worth noting that RememberMeAuthenticationFilter takes authenticationManager and RememberMeServices in its constructor.
Answer to your other question is that the authenticationManager doesn't need to know anything about remember me. It is the filter (or any class handling auto login) that needs to know about authenticationManager and RememberMeServices. (In other words, ask RememberMeServices for a token and pass it to authenticationManager to do auto login).
Spring Security's architecture is based on servlet filters. The sign-in mechanism you have implemented above is normally done by the UsernamePasswordAuthenticationFilter. Another filter called RememberMeAuthenticationFilter takes the responsibility for the remember-me functionality. The authenticationManager is not aware at all whether the remember-me feature is used by the application or not.
If you want to integrate Spring Security with another web-framework, first try to find out how the filters of the two frameworks can play together.