title: Spring Security and Azure AD PreAuthorize hasRole is not working
body: <p>I'm going through a <a href="https://docs.microsoft.com/en-us/azure/java/spring-framework/configure-spring-boot-starter-java-app-with-azure-active-directory#configure-and-compile-your-spring-boot-application" rel="nofollow noreferrer">tutorial</a> on Microsoft Docs on how to secure my Spring MVC application using Spring Boot Starter for Azure Active Directory. I'm trying to secure the admin area of my site. I have a @PreAuthorize annotation on a controller method that I only want users in the admin group to have access to. I am able to get a login prompt, but after succesfully logging in I get a 403 for that controller method. When I remove the @PreAuthorize annotation, I can log in and access the method just fine. </p>
  
  <p>Here is the controller method:</p>
  
  <pre><code>@Controller
  public class PostController {
  
      ...
  
      @PreAuthorize("hasRole('admin')")
      @RequestMapping(path = "/admin/post", method = RequestMethod.GET)
      public String getPost(@ModelAttribute("post") Post post, Model model) {
          List&lt;Tag&gt; tags = tagService.getAll();
          model.addAttribute("tags", tags);
          return "post";
      }
  
      ...
  </code></pre>
  
  <p>Here is the WebSecurityConfig.java:</p>
  
  <pre><code>@EnableWebSecurity
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
      @Autowired
      private OAuth2UserService&lt;OidcUserRequest, OidcUser&gt; oidcUserService;
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http
              .authorizeRequests()
              .antMatchers("/admin/**").authenticated()
              .and()
              .oauth2Login()
              .userInfoEndpoint()
              .oidcUserService(oidcUserService);
      }
  }
  </code></pre>
  
  <p>Here is the application.properties:</p>
  
  <pre><code># Azure AD
  # Specifies your Active Directory ID:
  azure.activedirectory.tenant-id=&lt;my-ad-tenant-id&gt;
  
  # Specifies your App Registration's Application ID:
  spring.security.oauth2.client.registration.azure.client-id=&lt;my-app-registration-app-id&gt;
  
  # Specifies your App Registration's secret key:
  spring.security.oauth2.client.registration.azure.client-secret=&lt;my-client-secret&gt;
  
  # Specifies the list of Active Directory groups to use for authorization:
  azure.activedirectory.activeDirectoryGroups=admin
  </code></pre>
  
  <p>Here is the app registration manifest:</p>
  
  <pre><code>{
      "id": "&lt;id&gt;",
      "acceptMappedClaims": null,
      "accessTokenAcceptedVersion": null,
      "addIns": [],
      "allowPublicClient": null,
      "appId": "&lt;app-id&gt;",
      "appRoles": [],
      "oauth2AllowUrlPathMatching": false,
      "createdDateTime": "2020-04-10T23:37:26Z",
      "groupMembershipClaims": null,
      "identifierUris": [],
      "informationalUrls": {
          "termsOfService": null,
          "support": null,
          "privacy": null,
          "marketing": null
      },
      "keyCredentials": [],
      "knownClientApplications": [],
      "logoUrl": null,
      "logoutUrl": null,
      "name": "test",
      "oauth2AllowIdTokenImplicitFlow": true,
      "oauth2AllowImplicitFlow": true,
      "oauth2Permissions": [],
      "oauth2RequirePostResponse": false,
      "optionalClaims": null,
      "orgRestrictions": [],
      "parentalControlSettings": {
          "countriesBlockedForMinors": [],
          "legalAgeGroupRule": "Allow"
      },
      "passwordCredentials": [
          {
              "customKeyIdentifier": null,
              "endDate": "2299-12-31T05:00:00Z",
              "keyId": "&lt;key-id&gt;",
              "startDate": "2020-04-10T23:39:47.917Z",
              "value": null,
              "createdOn": "2020-04-10T23:39:48.4572747Z",
              "hint": "SVb",
              "displayName": "test key"
          }
      ],
      "preAuthorizedApplications": [],
      "publisherDomain": "test.onmicrosoft.com",
      "replyUrlsWithType": [
          {
              "url": "http://localhost:8080/login/oauth2/code/azure",
              "type": "Web"
          }
      ],
      "requiredResourceAccess": [
          {
              "resourceAppId": "&lt;resource-app-id&gt;",
              "resourceAccess": [
                  {
                      "id": "&lt;resource-access-id&gt;",
                      "type": "Scope"
                  }
              ]
          }
      ],
      "samlMetadataUrl": null,
      "signInUrl": null,
      "signInAudience": "AzureADMyOrg",
      "tags": [],
      "tokenEncryptionKeyId": null
  }
  </code></pre>
  
  <p>Here's the group in Azure:</p>
  
  <p><a href="https://i.stack.imgur.com/YPLVr.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/YPLVr.png" alt="enter image description here"></a></p>
  
  <p>The user I'm signing in with is a member of this group. According to the documentation, only users that are not authorized should receive a 403. I've tried changing the hasRole() parameter to 'ROLE_admin' but that does not work. I've also tried to configure the hasRole("admin") in the WebSecurityConfig.java like this:</p>
  
  <pre><code>@Override
  protected void configure(HttpSecurity http) throws Exception {
      http
          .authorizeRequests()
          .antMatchers("/admin/**").authenticated()
          .antMatchers("/admin/**").hasRole("admin")
          .and()
          .oauth2Login()
          .userInfoEndpoint()
          .oidcUserService(oidcUserService);
  }
  </code></pre>
  
  <p>But that does not work either. I've been at this for a couple of days but I cannot figure out why I'm getting a 403 when the user I'm signing in with is in the admin group.</p>
  
  <p>EDIT</p>
  
  <p>pom.xml:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
      &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
      &lt;parent&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
          &lt;version&gt;2.2.5.RELEASE&lt;/version&gt;
      &lt;/parent&gt;
      &lt;groupId&gt;me.test&lt;/groupId&gt;
      &lt;artifactId&gt;test-me&lt;/artifactId&gt;
      &lt;version&gt;1.0&lt;/version&gt;
      &lt;packaging&gt;war&lt;/packaging&gt;
      &lt;name&gt;test.me&lt;/name&gt;
  
      &lt;properties&gt;
          &lt;java.version&gt;1.8&lt;/java.version&gt;
          &lt;azure.version&gt;2.2.0&lt;/azure.version&gt;
      &lt;/properties&gt;
  
      &lt;dependencies&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;com.microsoft.azure&lt;/groupId&gt;
              &lt;artifactId&gt;azure-active-directory-spring-boot-starter&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-security&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
              &lt;artifactId&gt;spring-security-oauth2-client&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
              &lt;artifactId&gt;spring-security-oauth2-jose&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.thymeleaf.extras&lt;/groupId&gt;
              &lt;artifactId&gt;thymeleaf-extras-springsecurity5&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;com.microsoft.sqlserver&lt;/groupId&gt;
              &lt;artifactId&gt;mssql-jdbc&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
              &lt;artifactId&gt;hibernate-validator&lt;/artifactId&gt;
              &lt;version&gt;6.1.0.Final&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-configuration-processor&lt;/artifactId&gt;
              &lt;optional&gt;true&lt;/optional&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.apache.commons&lt;/groupId&gt;
              &lt;artifactId&gt;commons-lang3&lt;/artifactId&gt;
              &lt;version&gt;3.9&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;com.azure&lt;/groupId&gt;
              &lt;artifactId&gt;azure-storage-blob&lt;/artifactId&gt;
              &lt;version&gt;12.5.0&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
              &lt;scope&gt;test&lt;/scope&gt;
              &lt;exclusions&gt;
                  &lt;exclusion&gt;
                      &lt;groupId&gt;org.junit.vintage&lt;/groupId&gt;
                      &lt;artifactId&gt;junit-vintage-engine&lt;/artifactId&gt;
                  &lt;/exclusion&gt;
              &lt;/exclusions&gt;
          &lt;/dependency&gt;
      &lt;/dependencies&gt;
  
      &lt;dependencyManagement&gt;
          &lt;dependencies&gt;
              &lt;dependency&gt;
                  &lt;groupId&gt;com.microsoft.azure&lt;/groupId&gt;
                  &lt;artifactId&gt;azure-spring-boot-bom&lt;/artifactId&gt;
                  &lt;version&gt;${azure.version}&lt;/version&gt;
                  &lt;type&gt;pom&lt;/type&gt;
                  &lt;scope&gt;import&lt;/scope&gt;
              &lt;/dependency&gt;
          &lt;/dependencies&gt;
      &lt;/dependencyManagement&gt;
  
      &lt;build&gt;
      &lt;finalName&gt;ROOT&lt;/finalName&gt;
          &lt;plugins&gt;
              &lt;plugin&gt;
                  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
              &lt;/plugin&gt;
              &lt;plugin&gt;
                  &lt;artifactId&gt;maven-failsafe-plugin&lt;/artifactId&gt;
                  &lt;executions&gt;
                      &lt;execution&gt;
                          &lt;goals&gt;
                              &lt;goal&gt;integration-test&lt;/goal&gt;
                              &lt;goal&gt;verify&lt;/goal&gt;
                          &lt;/goals&gt;
                      &lt;/execution&gt;
                  &lt;/executions&gt;
              &lt;/plugin&gt;
          &lt;/plugins&gt;
      &lt;/build&gt;
  
  &lt;/project&gt;
  </code></pre>
  
  <p>You can view the <a href="https://github.com/microsoft/azure-spring-boot/tree/master/azure-spring-boot-samples/azure-active-directory-spring-boot-backend-sample" rel="nofollow noreferrer">Microsoft Spring Boot / Azure AD sample</a> in GitHub.</p>