Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Is it possible to use OAuth2 for certain endpoints in my rest application and use basic authentication too for some other endpoints. It should all work on spring security version 2.0.1.RELEASE. I hope someone can help me further.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
242 views
Welcome To Ask or Share your Answers For Others

1 Answer

Yes, it's possible to use a basic authentication as well as an OAuth2 authentication intertwined, but I doubt you'll be able to set it up easily as HttpSecurity's authenticated() method doesn't allow you to pick which of your authentication method (oauth2Login/formLogin) will work.

However, there's a way to easily bypass that:

You could add a custom authority, let's call it ROLE_BASICAUTH, when an user connects using basic auth, and ROLE_OAUTH2 when an user connects using OAuth2. That way, you can use

.antMatchers("/endpoint-that-requires-basic-auth").hasRole("BASICAUTH")
.antMatchers("/endpoint-that-requires-oauth2").hasRole("OAUTH2")
    .anyRequest().authenticated()

When they reach an endpoint that you want basic authentication (and not OAuth2), you check their current authorities, and if it's not BASICAUTH, then you invalidate their session you display a login form without OAuth2 (to force them to use the basic authentication).

The downside to doing that is that you'd need to implement both a custom UserDetailsService as well as a custom OAuth2UserService...

But that's actually not that hard:

@Service
public class UserService extends DefaultOAuth2UserService implements UserDetailsService {

    // ...

    @Override
    public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException {
        OAuth2User user = super.loadUser(oAuth2UserRequest);

        Map<String, Object> attributes = user.getAttributes();
        Set<GrantedAuthority> authoritySet = new HashSet<>(user.getAuthorities());
        String userNameAttributeName = oAuth2UserRequest.getClientRegistration().getProviderDetails()
                .getUserInfoEndpoint().getUserNameAttributeName();

        authoritySet.add(new SimpleGrantedAuthority("ROLE_OAUTH2"));

        return new DefaultOAuth2User(authoritySet, attributes, userNameAttributeName);
    }


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserDetails user = getUserFromDatabase(username); // you'll need to provide that method (where are the username/password stored?)
        if (user == null) { // UserDetailsService doesn't allow loadUserByUsername to return null, so throw exception
            throw new UsernameNotFoundException("Couldn't find user with username '"+username+"'");
        }
        // add ROLE_BASICAUTH (you might need a custom UserDetails implementation here, because by defaut, UserDetails.getAuthorities() is immutable (I think, I might be a liar)
        return user;
    }

}

Note that this is a rough implementation, so you'll have to work it out a bit on your end as well.

You can also use this repository I made https://github.com/TwinProduction/spring-security-oauth2-client-example/tree/master/custom-userservice-sample as a guideline for the custom OAuth2UserService

Good luck.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...