javaspring-securityazure-spring-cloud

AD Authentication in Azure Spring Cloud causes 'Invalid CSRF token found'


AD Authentication with Azure Spring Cloud results in 'Invalid CSRF token found' event.

I have AD authentication with Azure Spring Cloud and after AD authentication, the redirect URL to the main page URL (https://${baseURL}/test) of my web app is successful.

However, when I try to use the link button on the main page to go to (https://${baseURL}/test/downlonad), I get the following error.

DEBUG                                   Securing GET /test
DEBUG                                   Set SecurityContextHolder to empty SecurityContext
DEBUG                                   Set SecurityContextHolder to anonymous SecurityContext
DEBUG                                   Failed to authorize filter invocation [GET /test] with attributes [authenticated]
WARN                                    Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [549] millisecond
DEBUG                                   Saved request https://${baseUrl}/test to session
DEBUG                                   Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, e
DEBUG                                   Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryP
DEBUG                                   Redirecting to https://${baseUrl}/oauth2/authorization/azure
DEBUG                                   Did not store empty SecurityContext
DEBUG                                   Did not store empty SecurityContext
DEBUG                                   Cleared SecurityContextHolder to complete request
DEBUG                                   Securing GET /oauth2/authorization/azure
DEBUG                                   Set SecurityContextHolder to empty SecurityContext
DEBUG                                   Redirecting to https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/v2.0/a
DEBUG                                   Did not store empty SecurityContext
DEBUG                                   Did not store empty SecurityContext
DEBUG                                   Cleared SecurityContextHolder to complete request
DEBUG                                   Securing GET /login/oauth2/code/azure?code=0.AXIAEto0y5gc-UmBsmgUVuIyUXDot_lt5nVOhl64iHht309yAFI.Ag
DEBUG                                   Set SecurityContextHolder to empty SecurityContext
DEBUG                                   HTTP POST https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/v2.0/token
DEBUG                                   Accept=[application/json, application/*+json]
DEBUG                                   Writing [{grant_type=[authorization_code], code=[0.AXIAEto0y5gc-UmBsmgUVuIyUXDot_lt5nVOhl64iHht309y
DEBUG                                   Response 200 OK
DEBUG                                   Reading to [org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse] as "applic
DEBUG                                   HTTP GET https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/discovery/v2.0/keys
DEBUG                                   Accept=[text/plain, application/xml, text/xml, application/json, application/*+xml, application/*+j2022-08-01 07:48:37     DEBUG                                   Response 200 OK
DEBUG                                   Reading to [java.lang.String] as "application/json;charset=utf-8"
DEBUG                                   Changed session id from 77C315072FEAE1AFDD26128B3689CAD1
DEBUG                                   Set SecurityContextHolder to OAuth2AuthenticationToken [Principal=Name: [user], Granted Authorit2022-08-01 07:48:38     DEBUG                                   Redirecting to https://${baseUrl}/test
DEBUG                                   Stored SecurityContextImpl [Authentication=OAuth2AuthenticationToken [Principal=Name: [user], Gr
DEBUG                                   Stored SecurityContextImpl [Authentication=OAuth2AuthenticationToken [Principal=Name: [user], Gr
DEBUG                                   Cleared SecurityContextHolder to complete request
DEBUG                                   Securing GET /test
DEBUG                                   Retrieved SecurityContextImpl [Authentication=OAuth2AuthenticationToken [Principal=Name: [user],
DEBUG                                   Set SecurityContextHolder to SecurityContextImpl [Authentication=OAuth2AuthenticationToken [Princip
DEBUG                                   Loaded matching saved request https://${baseUrl}/test
DEBUG                                   Authorized filter invocation [GET /test] with attributes [authenticated]
DEBUG                                   Secured GET /test
DEBUG                                   GET "/test", parameters={}
DEBUG                                   Mapped to Contoller#download


DEBUG Securing POST /test/download
DEBUG Retrieved SecurityContextImpl [Authentication=OAuth2AuthenticationToken [Principal=Name: [USER001],
DEBUG Set SecurityContextHolder to SecurityContextImpl [Authentication=OAuth2AuthenticationToken [Principal
DEBUG Invalid CSRF token found for https://${baseURL}/test/download
DEBUG Responding with 403 status code

Could you please advise as to the cause of the above?


<!doctype html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>test</title>
  <script type="text/javascript" th:src="@{/js/bootstrap.min.js}"></script>
  <script type="text/javascript" th:src="@{/js/jquery-3.6.0.min.js}"></script>
  <link rel="icon" th:href="@{/images/favicon.ico}">
</head>

<body>
  <div class="header_area">
    <img class="logo no_pointer" th:src="@{/images/logo.png}">
    <p th:text="${title}" class="mongon no_pointer"></p>
  </div>
        <div class="output_btn mt-4">
        <form method="post" th:action="@{/test/download}" id="test001" class="col-sm-7">
          <button type="button" class="btn btn-secondary button" id="test">link</button>
        </form>
        </div>
  <script type="text/javascript" th:src="@{/js/test.js}"></script>
</body>

</html>
@RestController
public class HomeController {

    @GetMapping("/test/download")
    public String download(HttpServletRequest request) {
        String message = "test";
        return message;
    }
}

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
        credential:
          client-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
          client-secret: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
        redirect-uri-template: https://${baseURL}/login/oauth2/code/azure

Solution

  • According to the example in Secure REST API using Spring Security 5 and Azure Active Directory, it mentioned using @PreAuthorize Annotation in the Controller code.

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.security.access.prepost.PreAuthorize;
    
    @RestController
    public class HelloController {
         @GetMapping("Admin")
         @ResponseBody
         @PreAuthorize("hasAuthority('APPROLE_Admin')")
         public String Admin() {
             return "Admin message";
         }
    }
    

    For more details about this annotation, please kindly check