Skip to content

Discovering Azure #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
heruan opened this issue Aug 17, 2022 · 1 comment
Closed

Discovering Azure #13

heruan opened this issue Aug 17, 2022 · 1 comment
Assignees

Comments

@heruan
Copy link
Member

heruan commented Aug 17, 2022

Part of #10

@heruan heruan self-assigned this Aug 17, 2022
@heruan
Copy link
Member Author

heruan commented Aug 18, 2022

Setting up an instance of Azure Active Directory

  • Subscribing for a free trial of Azure AD: https://azure.microsoft.com/en-us/free/active-directory/
  • From the Azure portal, it is pretty straightforward how to create a new user from the "Users" section
  • A client for authentication can be created from the "App Registrations" section

Spring integration

Azure provides an official Spring integration to get OIDC authentication:

        <dependency>
            <groupId>com.azure.spring</groupId>
            <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
        </dependency>

This brings in a lot of unneeded dependencies for other Azure services (such as graph, storage, etc.) but it's a good start to avoid reinventing the wheel.

To configure the add-on we just need to put some entries into application.yml:

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant-id-from-azure-portal>
        credential:
          client-id: <client-id-from-azure-portal>
          client-secret: <client-secret-from-azure-portal>

The Azure Spring add-on works out-of-the-box for a plain Spring MVC app, but it doesn't cope well with a Vaadin app which requires a more complex security configuration for URLs such as JS bundles, heartbeats, etc.

We then need to mix Vaadin's and Azure's security needs: this can be done extending VaadinWebSecurityConfigurerAdapter (which contains already all the configuration Vaadin needs to work) and add there what Azure needs. Azure Spring add-on comes with its own AadWebSecurityConfigurerAdapter, from which we can get the needed configuration:

@Configuration
@EnableWebSecurity
public class AzureSecurityConfiguration
        extends VaadinWebSecurityConfigurerAdapter {

    @Autowired
    protected ClientRegistrationRepository repo;

    @Autowired
    protected OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;

    @Autowired
    protected AadAuthenticationProperties properties;

    @Autowired
    protected ObjectProvider<OAuth2ClientAuthenticationJwkResolver> jwkResolvers;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        // @formatter:off
        http.oauth2Login()
                .authorizationEndpoint()
                    .authorizationRequestResolver(requestResolver())
                    .and()
                .tokenEndpoint()
                    .accessTokenResponseClient(accessTokenResponseClient())
                    .and()
                .userInfoEndpoint()
                    .oidcUserService(oidcUserService)
                    .and()
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(oidcLogoutSuccessHandler());
        // @formatter:off

        Filter conditionalAccessFilter = conditionalAccessFilter();
        if (conditionalAccessFilter != null) {
            http.addFilterAfter(conditionalAccessFilter, OAuth2AuthorizationRequestRedirectFilter.class);
        }
    }

    protected Filter conditionalAccessFilter() {
        return null;
    }

    protected LogoutSuccessHandler oidcLogoutSuccessHandler() {
        OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler =
            new OidcClientInitiatedLogoutSuccessHandler(this.repo);
        String uri = this.properties.getPostLogoutRedirectUri();
        if (StringUtils.hasText(uri)) {
            oidcLogoutSuccessHandler.setPostLogoutRedirectUri(uri);
        }
        return oidcLogoutSuccessHandler;
    }

    protected OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient() {
        DefaultAuthorizationCodeTokenResponseClient result = new DefaultAuthorizationCodeTokenResponseClient();
        if (repo instanceof AadClientRegistrationRepository) {
            AadOAuth2AuthorizationCodeGrantRequestEntityConverter converter =
                new AadOAuth2AuthorizationCodeGrantRequestEntityConverter(
                    ((AadClientRegistrationRepository) repo).getAzureClientAccessTokenScopes());
            OAuth2ClientAuthenticationJwkResolver jwkResolver = jwkResolvers.getIfUnique();
            if (jwkResolver != null) {
                converter.addParametersConverter(new AadJwtClientAuthenticationParametersConverter<>(jwkResolver::resolve));
            }
            result.setRequestEntityConverter(converter);
        }
        return result;
    }

    protected OAuth2AuthorizationRequestResolver requestResolver() {
        return new AadOAuth2AuthorizationRequestResolver(this.repo, properties);
    }
}

Once added this we will be redirected to Azure login page when we try to access the Vaadin app and redirected back once successfully authenticated. Once authenticated, we can get authentication information from Spring's security-context:

var authentication = SecurityContextHolder.getContext().getAuthentication();
var user = (OidcUser) authentication.getPrincipal();
var name = user.getFullName();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant