0
votes

I have to design a application for an organization where Authentication need to be happen Using SSO with Azure Directory using spring boot.

All the employee Information is stored in the AD. My custom application will have it's own users and their roles which are saved in the Database. Not every Employee in the organization will have access to this application. Admin will add user and their roles in Database(Mysql).

I am able to figure it out to do SSO with AD by adding relevant details in properties-file and configuring WebSecurify Config class

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   @Autowired
   private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;

   @Autowired
   private AADAuthenticationFilter aadAuthFilter;


   @Override
   protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests().antMatchers(HttpMethod.OPTIONS, 
             "/**").permitAll().anyRequest().authenticated()
            .and()
            .oauth2Login()
            .userInfoEndpoint()
            .oidcUserService(oidcUserService);

    http
            .addFilterBefore(aadAuthFilter, UsernamePasswordAuthenticationFilter.class);

    http
            .headers()
            .frameOptions().sameOrigin()
            .cacheControl();

       http
              .csrf().disable()
              .authorizeRequests().antMatchers(HttpMethod.OPTIONS, 
              "/**").permitAll().anyRequest().authenticated()
     }

 }

Once the user is validated, In response i will get JWT token, Which i will use for all my further API requests. But the Problem is, Here i am allowing all the Employees to access the application since he is authenticated using AD. But, Once User is Authenticated i want to check whether user is available in the database or not, If he is not available, i need to send invalid user, if he is valid user to my application, i need to fetch roles and send it to front end as a Valid response.

I also want to do service level authorization for the user, I have used @PreAuthorize Annotation for most of my services. @PreAuthorize("hasRole('ROLE_VIEWER') or hasRole('ROLE_EDITOR')")

Edit 1

public class UserDetailsServiceImpl extends OidcUserService implements 
CustomUserDetailsService {
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws 
OAuth2AuthenticationException {

    OidcUser oidcUser;

    String mail=userRequest.getClientRegistration().getRegistrationId();

     Set<GrantedAuthority> grantedAuthorities = getAuthorities(mail);

    oidcUser = new DefaultOidcUser(grantedAuthorities, 
    userRequest.getIdToken());

    return oidcUser;


}

private Set<GrantedAuthority> getAuthorities(String email) {
      List<RoleIdDetails> 
     roleIdDetails=usersRepository.getRoleIdDeatils(email);
       final Set<GrantedAuthority> authorities = 
    roleIdDetails.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + 
  role.getRoleName().toString().toUpperCase())).collect(Collectors.toSet());
    return authorities;
   }
 } 

I have updated With My Own Custom OidcUserService, But Still I'm not able to set the roles.

1
we have done something similar, during AD authentication we save the username coming from AD service and then, check in the database. Isn't it possible for you to add the same check in 'aadAuthFilter'. Are you able to get the username ??user9065831
@AmanGarg Can u please direct me to a resource (or) provide a working example on how to do this. Thank you.Karthik
One way could be in oidcUserService in method public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException, oidcUser implements DefaultOAuth2User class. call getName method to get the username and then, check user in DB in loadUser method itself, Ref: github.com/spring-projects/spring-security/blob/master/oauth2/…user9065831
@AmanGarg I have updated with custom OidcUserService, But still no use. Updates latest code is provided in Edit 1Karthik

1 Answers

0
votes

Per my understanding, you don't need to use Mysql database to store the user and their roles, we can implement this requirement just by Azure Active Directory.

First, we can create a group in Azure Active Directory by clicking "Groups" --> "New group" buttons on azure portal and select the members which you want to this group from the employee in you azure ad(shown as below screenshots): enter image description here

enter image description here

enter image description here

Then go to your application in azure ad by clicking "App registrations" and click "Manifest" button. enter image description here

You can also add more roles under the "appRoles" property in the screenshot above.

After that, in your application in azure ad, please click "Managed application in local directory". enter image description here

Then click "Users and groups" --> "Add user". enter image description here

Choose the group which we created just now and select a role for it. enter image description here

Now you can do service level authorization for the user by the annotation you mentioned in your question(@PreAuthorize), you can also refer to this tutorial.

By the way, if we want to assign a role to a group in azure ad, we need to have Premium P1 or P2 plan for azure ad(Azure Active Directory pricing). If you don't have Premium plan, you can just assign a role to each user but not a group in the last screenshot.