Commit a691f54c authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Removed Spring Security: calls handled using IA2 AuthLib

parent d9c5b66f
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -24,15 +24,6 @@
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
@@ -42,6 +33,16 @@
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>AuthLib</artifactId>
            <version>2.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
+0 −35
Original line number Diff line number Diff line
package it.inaf.ia2.gms.authn;

import java.util.Collection;
import java.util.Map;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.common.OAuth2AccessToken;

public class CustomAuthenticationData extends UsernamePasswordAuthenticationToken {

    private final Map<String, Object> attributes;
    private final OAuth2AccessToken accessToken;
    private final String refreshToken;

    public CustomAuthenticationData(String username, Map<String, Object> attributes,
            Collection<? extends GrantedAuthority> authorities,
            OAuth2AccessToken accessToken, String refreshToken) {
        super(username, "N/A", authorities);
        this.attributes = attributes;
        this.accessToken = accessToken;
        this.refreshToken = refreshToken;
    }

    public Map<String, Object> getAttributes() {
        return attributes;
    }

    public OAuth2AccessToken getAccessToken() {
        return accessToken;
    }

    public String getRefreshToken() {
        return refreshToken;
    }
}
+0 −42
Original line number Diff line number Diff line
package it.inaf.ia2.gms.authn;

import it.inaf.ia2.gms.persistence.LoggingDAO;
import java.util.List;
import java.util.Map;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore;

public class CustomIdTokenConverter extends DefaultUserAuthenticationConverter {

    private final JwkTokenStore jwkTokenStore;
    private final LoggingDAO loggingDAO;

    public CustomIdTokenConverter(JwkTokenStore jwkTokenStore, LoggingDAO loggingDAO) {
        this.jwkTokenStore = jwkTokenStore;
        this.loggingDAO = loggingDAO;
    }

    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {

        String idTokenString = (String) map.get("id_token");
        String accessTokenString = (String) map.get("access_token");

        OAuth2AccessToken token = jwkTokenStore.readAccessToken(idTokenString);
        OAuth2AccessToken accessToken = jwkTokenStore.readAccessToken(accessTokenString);
        String refreshToken = (String) map.get("refresh_token");

        Map<String, Object> claims = token.getAdditionalInformation();

        String principal = (String) claims.get("sub");
        loggingDAO.logAction("Login by " + principal);

        List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");

        return new CustomAuthenticationData(principal, claims, authorities, accessToken, refreshToken);
    }
}
+0 −70
Original line number Diff line number Diff line
package it.inaf.ia2.gms.authn;

import java.util.Map;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;

/**
 * Retrieve token data from the user info / check token endpoint using the
 * returned access token.
 */
public class GetTokenDataService implements ResourceServerTokenServices {

    private final RestOperations restTemplate = new RestTemplate();

    private String checkTokenEndpointUrl;

    private String clientId;

    private AccessTokenConverter tokenConverter;

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public void setCheckTokenEndpointUrl(String checkTokenEndpointUrl) {
        this.checkTokenEndpointUrl = checkTokenEndpointUrl;
    }

    public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) {
        this.tokenConverter = accessTokenConverter;
    }

    @Override
    public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException {

        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
        formData.add("client_id", clientId);

        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + accessToken);
        Map<String, Object> map = postForMap(checkTokenEndpointUrl, formData, headers);

        return this.tokenConverter.extractAuthentication(map);
    }

    private Map<String, Object> postForMap(String path, MultiValueMap<String, String> formData, HttpHeaders headers) {
        if (headers.getContentType() == null) {
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        }
        return restTemplate.exchange(path, HttpMethod.POST,
                new HttpEntity<>(formData, headers), Map.class).getBody();
    }

    @Override
    public OAuth2AccessToken readAccessToken(String accessToken) {
        throw new UnsupportedOperationException("Not supported: read access token");
    }
}
+41 −0
Original line number Diff line number Diff line
package it.inaf.ia2.gms.authn;

import it.inaf.ia2.aa.LoginFilter;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.springframework.util.AntPathMatcher;

public class GmsLoginFilter extends LoginFilter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;

        if (shouldNotFilter(request)) {
            fc.doFilter(req, res);
        } else {
            super.doFilter(req, res, fc);
        }
    }

    private boolean shouldNotFilter(HttpServletRequest request) throws ServletException {

        // Allow CORS check
        if ("OPTIONS".equals(request.getMethod())) {
            return true;
        }

        AntPathMatcher pathMatcher = new AntPathMatcher();

        // Authentication is ignored for these endpoints:
        return Arrays.asList("/ws/jwt/**", "/error", "/logout", "/invited-registration", "/help/**")
                .stream()
                .anyMatch(p -> pathMatcher.match(p, request.getServletPath()));
    }
}
Loading