Skip to content

Common holder for authenticated user information #14

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 18, 2022 · 3 comments · Fixed by #30
Closed

Common holder for authenticated user information #14

heruan opened this issue Aug 18, 2022 · 3 comments · Fixed by #30
Assignees
Labels
core enhancement New feature or request

Comments

@heruan
Copy link
Member

heruan commented Aug 18, 2022

When authenticating against an OIDC provider with Spring, we can find user information using the Authentication.getPrincipal() method.

The method signature returns a generic Object, so each provider might return different types.

Prototyping with the three selected providers turns out:

To provide a consistent API, we should provide a common holder for these informations, such as a VaadinUser object. An instance of said type would then be filled with informations from each provided and available in the Vaadin session or by bean injection.

@heruan heruan added enhancement New feature or request core labels Aug 18, 2022
@heruan heruan self-assigned this Aug 19, 2022
@heruan
Copy link
Member Author

heruan commented Aug 19, 2022

Update on this: using only Spring to configure OIDC (no provider's libraries) and setting the correct scopes (profile and openid) we get an instance of OidcUser from all the three providers.

We might still want to provide a Vaadin wrapper for user information, to be used for example with other authentication method (e.g. internal form), but it comes easier to build one from the same interface.

The OIDC standard defines the concept of claim (see spec) as a piece of information that is provided about the user. Several claims are already defined by the standards, and they're all mapped to OidcUser properties (via StandardClaimAccessor).

@heruan heruan removed their assignment Aug 23, 2022
@DiegoCardoso DiegoCardoso self-assigned this Aug 23, 2022
@heruan
Copy link
Member Author

heruan commented Aug 25, 2022

We should investigate if this way of injecting the authentication principal works in Vaadin views and, if not, why:

@Route("/foo")
public class MyView extends VerticalLayout {

    public MyView(@AuthenticatedPrincipal OidcUser user) {
        // ...
    }
}

The other method to get the user instance is statically from the Authentication object:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
OidcUser user = (OidcUser) auth.getPrincipal();

Spring's OAuth2LoginConfigurer has also a method to set a login success handler that we can use to get the OidcUser instance and set it somewhere later accessible, like:

        oauth2Login.successHandler((req, res, auth) -> {
                            OidcUser user = (OidcUser) auth.getPrincipal();
                            // set the user somewhere, like req.getSession()
                        });

@heruan
Copy link
Member Author

heruan commented Aug 29, 2022

We could provide accessors to the user object via an injectable context bean, something like:

interface VaadinAuthContext {

   Optional<OidcUser> getAuthenticatedUser();
}

And then expose it in the starter as a bean:

@Configuration
public class VaadinAuthSecurityConfiguration extends VaadinWebSecurity {
    // ...
    @Bean
    public VaadinAuthContext getAuthContext() {
        return () -> Optional.of(SecurityContextHolder.getContext())
                             .map(SecurityContext::getAuthentication)
                             .map(Authentication::getPrincipal)
                             .filter(OidcUser.class::isInstance)
                             .map(OidcUser.class::cast);
    }
}

Then the bean would be injectable in Vaadin views and used to get the authenticated user, e.g.

@Route("/foo")
public class FooView extends VerticalLayout {

    public FooView(VaadinAuthContext authContext) {
        authContext.getAuthenticatedUser().ifPresentOrElse(
            user -> add(new Text("Hello " + user.getFullName())),
            () -> add(new Text("You are not authenticated."));
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants