0
votes

I am trying to create a login page which will log in into the specific account depending on which role does the user have but for some reason the spring security never recogonizes the username and password

Here is the LoginController

package login_page

import grails.plugin.springsecurity.userdetails.DefaultPostAuthenticationChecks import org.springframework.security.access.annotation.Secured

@Secured('permitAll') class LoginController extends grails.plugin.springsecurity.LoginController {

PersonService personService

def index() {
    if (isLoggedIn()) {
        redirect uri: conf.successHandler.defaultTargetUrl
    }
    else {
        redirect action: 'auth', params: params
    }
}
def auth() {

    def conf = getConf()

    if (isLoggedIn()) {
        redirect uri: conf.successHandler.defaultTargetUrl
        return
    }

    String postUrl = request.contextPath + conf.apf.filterProcessesUrl
    render view: 'index', model: [postUrl: postUrl,
                                 rememberMeParameter: conf.rememberMe.parameter,
                                 usernameParameter: conf.apf.usernameParameter,
                                 passwordParameter: conf.apf.passwordParameter,
                                ]
}

}

and success uri is /person/LoginPage

and the LoginPage method is this

   @Secured(['ROLE_USER','ROLE_ADMIN','ROLE_SUPERADMIN'])
def LoginPage() {
      refreshCurrentUser()
    if (currentPerson == null) {
        notFound()
    }else {
        if(currentPerson.getAuthorities()[0].getAuthority()=="ROLE_SUPERADMIN"){
            redirect(controller:'superAdmin', action: 'superAdminShow', id: currentPerson.id)
        }
       else if(currentPerson.getAuthorities()[0].getAuthority()=="ROLE_ADMIN"){
            redirect(controller:'admin', action: 'adminShow', id: currentPerson.id)
        }
        else if(currentPerson.getAuthorities()[0].getAuthority()=="ROLE_USER"){
            redirect(action: 'show', id: currentPerson.id)
        }
    }
}
1
Also guys I have a custom login page with form action :- /login/authenticate - Soham Patel
spring is really ticklish about security, if it is in the path when stating spring-boot, it will kick in, blocking everything because it is not configured. - efekctive
Yes true and thats why I am overriding index and auth method but for some reason it won't recognize the username and password that I have for the person objects - Soham Patel
My point is that when the security jar is in the path, and no security changes are in place, it usually returns permission errors until security is set, at this is my spring-boot experience - efekctive
So we would set the security by giving username and password credentials right? - Soham Patel

1 Answers

0
votes

This is a very simple security configuration that I put together on the fly (a Reactive Java Rest API) for a silly demo. I am by no means a security expert, but it can give you an idea of the things involved.

import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import XXXXXXXX.Permissions;
import XXXXXXXXX.UserPermissions;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity.AuthorizeExchangeSpec;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import reactor.core.publisher.Mono;


@Configuration
@EnableWebFluxSecurity
public class ApiSecurityConfiguration implements ReactiveAuthenticationManager{

    @Autowired
    Permissions permissions;
    @Autowired
    RedisTemplate<String, Object> redisCache;

    private static final Logger logger = LoggerFactory.getLogger(ApiSecurityConfiguration.class);
    private UserPermissions userPermissionTable;

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        AuthorizeExchangeSpec authorize;
        http.formLogin().disable();
        http.csrf().disable();
        http.logout().disable();å
        http.httpBasic().disable();
        http.httpBasic().
        authenticationManager(this::authenticate);
        authorize = http.authorizeExchange();
        authorize.anyExchange().access(this::check);

        return http.build();
    }

    private Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext context) {
        return authentication.map(a ->this.checkAuthorizations(a, context)).map(granted -> new AuthorizationDecision(granted));
    }

    private boolean checkAuthorizations(Authentication a, AuthorizationContext context){
        boolean ret = false;
        String name = a.getName();
        if (a.isAuthenticated()){
            logger.info(String.format("FOUND %s, authorizing...", name));
            ret = userPermissionTable.canAccess("XXXX", context.getExchange().getRequest().getPath().value(), context.getExchange().getRequest().getMethodValue());
            logger.info(String.format("%s access granted: %B", name, ret));
        }
        return ret;
    }

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        CompletableFuture<UserPermissions> cup;
        Authentication auth;
        String name = null;

        auth = authentication;
        auth.setAuthenticated(false);
        try {
            name = authentication.getName();
            logger.info(String.format("Looking %s in cache...", name));
            userPermissionTable = (UserPermissions)redisCache.opsForValue().get(name);
            if (userPermissionTable == null){
                logger.info(String.format("NOT in cache, authenticating: %s ...", name));
                cup = permissions.getPermissionsForUser(name, authentication.getCredentials().toString());
                userPermissionTable = cup.get(1000, TimeUnit.MILLISECONDS);
                redisCache.opsForValue().set(name, userPermissionTable, userPermissionTable.getTTL(), TimeUnit.MINUTES);
                auth = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), null);
                logger.info(String.format("Authenticated: %s", name));
            }
            else{
                auth = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), null);
                redisCache.expire(name, userPermissionTable.getTTL(), TimeUnit.MINUTES);
            }
        } catch (Exception e) {
            logger.info(String.format("FAILED to authenticate: %s", name));
        }
        return Mono.just(auth);
    }
}