spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.78k stars 5.89k forks source link

OAuth2: auto-redirect if only one provider is configured still redirects to login page. #7586

Open elch78 opened 4 years ago

elch78 commented 4 years ago

Summary

Oauth2 Auto-redirect if there is only one provider configured does not work.

Actual Behavior

Redirect to login page

Expected Behavior

redirect to provider

Configuration

See example https://github.com/elch78/spring-security-7586.git

Version

5.1.6.RELEASE

Sample

I've debugged the code and found these 2 places

This one works as expected OAuth2LoginConfigurer.init()

if (loginUrlToClientName.size() == 1) { // Setup auto-redirect to provider login page // when only 1 client is configured this.updateAuthenticationDefaults(); this.updateAccessDefaults(http); String providerLoginPage = loginUrlToClientName.keySet().iterator().next(); this.registerAuthenticationEntryPoint(http, this.getLoginEntryPoint(http, providerLoginPage)); }

This one is probably the one with the bug. It's invoked with providerLoginPage=/oauth2/authorization/ciam which is correct I guess. Ciam is our IDP.

OAuth2LoginConfigurer

` private AuthenticationEntryPoint getLoginEntryPoint(B http, String providerLoginPage) { RequestMatcher loginPageMatcher = new AntPathRequestMatcher(this.getLoginPage()); RequestMatcher faviconMatcher = new AntPathRequestMatcher("/favicon.ico"); RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher(http); RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher( new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);

    RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
            new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));

    LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
    entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)),
            new LoginUrlAuthenticationEntryPoint(providerLoginPage));

    DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
    loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint());

    return loginEntryPoint;
}`

The last line results in setDefaultEntryPoint with LoginUrlAuthenticationEntryPoint and loginFormUrl="/login"

elch78 commented 4 years ago

Related to https://github.com/spring-projects/spring-security/issues/6802

rwinch commented 4 years ago

I think you are right. This looks like a duplicate of gh-6802 Can you confirm or explain how they are different?

elch78 commented 4 years ago

I understood that in your case you have a form login in addition to OAuth2 and still want the login page despite only one oauth provider being configured.

elch78 commented 4 years ago

I made an attempt to fix this here

The unit test is green, but I'm not so confident that it's enough since I removed quite a bit of the logic in getLoginEntryPoint method. Maybe we can discuss my changes.