简体   繁体   中英

Disable CSRF in spring-boot application with OAuth2 SSO

I have a spring-boot service that authenticates users with Okta Platform API using OpenID Connect/OAuth2. When users try to access my service, they are redirected to Okta sign-on page and authenticated, then Okta redirects them back to my service.

Here is relevant part of my pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Here is my controller code:

@RestController
@EnableOAuth2Sso
@SpringBootApplication
public class Application {

    @RequestMapping(path = "/", method = RequestMethod.GET)
    public String home(Authentication auth) {
        return "Home: " + auth.getName();
    }

    @RequestMapping(path = "/app", method = RequestMethod.POST)
    public String app(Authentication auth) {
        return "App: " + auth.getName();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

This works perfectly for the first GET controller method but for the second POST method my service requires me to provide CSRF token. I want to disable CSRF check entirely, so I added this to my app

@Configuration
@EnableOAuth2Sso
public class Config extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }
}

However, after adding the above configuration my service stopped authenticating users with Okta (is no longer redirecting unauthenticated requests to Okta). It's directly calling home() method with null parameter.

I followed this blog post to create my service https://developer.okta.com/blog/2017/03/21/spring-boot-oauth

How can I disable CSRF entirely while still using OAuth2 SSO authentication with Okta?

I ran into exactly the same issue. After some digging into how the HttpSecurity class works I modified the configure() function as follows:

    @EnableWebSecurity
public static class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.authorizeRequests().anyRequest().authenticated().and().oauth2Login().and().csrf().disable();
    }
}

Adding the builder clauses authorizeRequests().anyRequest().authenticated().and().oauth2Login() forces the controller to intercept requests with OAuth authentication. You'll find this fully documented inside the Spring HttpSecurity.java source code.

Just to be sure I modified all my REST endpoint methods to include the token as an argument and I could see with the original version of the configure() method the token was null but once I added the extra clauses the token was included.

You need to disable the CSRF token for your /app endpoint only. Try with this:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.mvcMatcher("/app").csrf().disable();
}
@Configuration
@EnableOAuth2Sso
public class Config extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }
}

this doesn't worked for me . Instead I added csrf header for each post requests. Here is the code to get the csrf token.

If you are using thymeleaf, then add the following to get the CSRF token in your .html file

<html xmlns:th="http://www.thymeleaf.org">
<script th:inline="javascript">
function getToken(){
        var _csrf_token = [[${_csrf.token}]] ;
        var _csrf_param_name = [[${_csrf.parameterName}]];
        console.log(_csrf_token);
        return _csrf_token;
    }
</script>
</html>

then put this in your ajax request as header

function sampleFunc(url, token) {


        $.ajax({
            type : 'POST',
            contentType : "application/json",
            url : '/storeTokens',
            beforeSend : function(xhr) {
                xhr.setRequestHeader('X-CSRF-TOKEN', token);
            },
            data : jsonObject
        // dataType : 'html'
        }).done(function(data) {
            console.log("success");

        }).fail(function(jqXhr) {
            var a = jqXhr;
        });

    }

This worked for me..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM