Giter VIP home page Giter VIP logo

Comments (10)

nikos avatar nikos commented on July 4, 2024 3

After further experimentation with Spring Security 5.1 it turns out that with a valid JWT at hand, securing your resources in your Spring Boot application is as straight forward as:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/resources/**", "/error");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .mvcMatchers("/products/**").hasAuthority("MYROLE")
                .and()
                  .oauth2ResourceServer()
                    .jwt()
                      .jwkSetUri("http://localhost:9011/.well-known/jwks.json")
                      .jwtAuthenticationConverter(grantedAuthoritiesExtractor())
        // this disables session creation on Spring Security
        //.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        ;
    }

    private Converter<Jwt, AbstractAuthenticationToken> grantedAuthoritiesExtractor() {
        return new JwtAuthenticationConverter() {
            @Override
            protected Collection<GrantedAuthority> extractAuthorities(Jwt jwt) {
                Collection<String> authorities = (Collection<String>) jwt.getClaims().get("roles");
                return authorities.stream()
                        .map(SimpleGrantedAuthority::new)
                        .collect(Collectors.toList());
            }
        };
    }
}

from fusionauth-spring-security.

damienherve avatar damienherve commented on July 4, 2024 2

I upvoted this issue because i encountered the exact same problem. The filter given in this library is only useful for the Authorization Code grant, by analyzing the token in response of the redirectUri after a succesful login.

I made a custom TokenFilter that i register in the security chain, which check the validity of the token (with the public certificate), and then extract the informations needed in the JWT to create an authenticated user, with authorities extracted from the 'roles' key in the claims.

If i have time, i'll submit a PR of my work to help people, but for the moment the class is not generic at all and only fits to my specific needs...

from fusionauth-spring-security.

designermonkey avatar designermonkey commented on July 4, 2024 2

Does anyone have any news for us non-java devs on how this may be going? Is there a simple method for allowing our customers apps to authenticate with our APIs using client_credentials?

from fusionauth-spring-security.

robotdan avatar robotdan commented on July 4, 2024

Hi @nikos thanks for the question.

FusionAuth does not currently support the client credentials grant, this will likely be coming this summer with a suite of IoT features.

We could look into adding the Password grant to this library, or if you'd like to submit a PR that would be great as well.

I'm not a Spring expert at all... so without digging back into the code your guess is as good as mine. If I have some cycles to take a look and see if I can stub it out I'll report back.

If you're looking to use the password or credentials grant, does this mean you'll be using it for something other than a normal web login workflow?

from fusionauth-spring-security.

tyduptyler13 avatar tyduptyler13 commented on July 4, 2024

Hi,

I recently heard that spring started including an OpenID Connect feature and I haven't had the time to look into it. When I get the chance I will update our example code to use the latest spring features.

from fusionauth-spring-security.

nikos avatar nikos commented on July 4, 2024

@tyduptyler13

I recently heard that spring started including an OpenID Connect feature and I haven't had the time to look into it. When I get the chance I will update our example code to use the latest spring features.

Hi Typler, are you refering to the changes in Spring Security 5.1.x ?
https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Features-Matrix
Might be quite an impact worth a new branch since there seem many changes compared to Spring Security OAuth 2.x

from fusionauth-spring-security.

nikos avatar nikos commented on July 4, 2024

@damienherve my current approach is to make use of Spring's "standard" class when it comes to the password grants flow: org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails and add userInfoUri for accessing OpenID metadata.

OpenIDResourceDetails

package io.fusionauth.patch.oauth;

import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;

public interface OpenIDResourceDetails extends OAuth2ProtectedResourceDetails {

    String getUserInfoUri();

    void setUserInfoUri(String userInfoUri);

}

OpenIDPasswordResourceDetails

package io.fusionauth.patch.oauth;

import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails;

public class OpenIDPasswordResourceDetails extends ResourceOwnerPasswordResourceDetails implements OpenIDResourceDetails {

    private String userInfoUri;

    public String getUserInfoUri() {
        return userInfoUri;
    }

    public void setUserInfoUri(String userInfoUri) {
        this.userInfoUri = userInfoUri;
    }

}

OpenIDConnectFilter

package io.fusionauth.patch.oauth;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import io.fusionauth.security.FusionAuthUserDetails;

// Patches io.fusionauth.security.OpenIDConnectFilter
public class OpenIDConnectFilter extends AbstractAuthenticationProcessingFilter {

    private final OpenIDResourceDetails openIDResourceDetails;
    private final OAuth2RestOperations restTemplate;

    public OpenIDConnectFilter(String defaultFilterProcessesUrl, OpenIDResourceDetails openIDResourceDetails, OAuth2RestOperations restTemplate) {
        super(defaultFilterProcessesUrl);
        this.openIDResourceDetails = openIDResourceDetails;
        this.restTemplate = restTemplate;
        setAuthenticationManager(new NoopAuthenticationManager());
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        OAuth2AccessToken accessToken;
        try {
            accessToken = restTemplate.getAccessToken();
        } catch (final OAuth2Exception e) {
            throw new BadCredentialsException("Could not obtain access token", e);
        }
        try {
            FusionAuthUserDetails user = new FusionAuthUserDetails(getUserInfo(accessToken), accessToken);
            return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        } catch (Exception e) {
            throw new BadCredentialsException("Failed to validate the token", e);
        }
    }

    private JsonNode getUserInfo(OAuth2AccessToken accessToken) throws IOException {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + accessToken.getValue());

        HttpEntity<String> httpEntity = new HttpEntity<>(headers);
        ResponseEntity<String> response = new RestTemplate().exchange(openIDResourceDetails.getUserInfoUri(), HttpMethod.GET, httpEntity, String.class);
        if (response.getStatusCode() == HttpStatus.OK) {
            return new ObjectMapper().readTree(response.getBody());
        }

        throw new BadCredentialsException("Failed to request user details from the UserInfo API. " +
                "Status code [" + response.getStatusCodeValue() + "] Message [" + response.getBody() + "]");
    }

    private static class NoopAuthenticationManager implements AuthenticationManager {
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            throw new UnsupportedOperationException("No authentication should be done with this AuthenticationManager");
        }
    }
}

from fusionauth-spring-security.

tyduptyler13 avatar tyduptyler13 commented on July 4, 2024

I started working on a new example, based on how its going I think this repo will be deprecated in favor of just using spring security 5.

https://github.com/FusionAuth/fusionauth-spring-security-example/tree/SpringSecurity5

from fusionauth-spring-security.

vlvinogr avatar vlvinogr commented on July 4, 2024

Any update to support client_credentials grant type? thank you

from fusionauth-spring-security.

robotdan avatar robotdan commented on July 4, 2024

FusionAuth does not currently support the client credentials grant.

See FusionAuth feature request and ensure to upvote it.
FusionAuth/fusionauth-issues#155

If you have a business requirement for this, hit the FusionAuth Contact form and we can provide you a quote with a timeline.

Thanks!

from fusionauth-spring-security.

Related Issues (4)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.