How to get different types of authentication in Thymeleaf

18 views Asked by At

In my Spring Boot application i have two login types(form login and Oauth2.0)

When i succesfully authenticate, into СontextHolder spring put UserDetails or OAuth2UserService depending on the type of authorization I went through. However, since different objects are placed in the context, they must always be addressed differently. If the principal is inherited from OidcUser then in Thymeleaf you need to contact {#authentication.principal.getEmail()} and if from regular UserDetails then {#authentication.principal.username}. The problem is that I want to display this information in the header, which is a fragment that is inserted onto all pages. Therefore, passing the authentication type into the model is not suitable. I also tried other methods, but nothing helped. The instanceof operator is also not provided in Thymelea

This is my Security Configuration

public class SpringWebSecurityConfigurer {

    private final UserService userService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
               .anonymous(AbstractHttpConfigurer::disable)
               .authorizeHttpRequests(authorize -> authorize
                       .requestMatchers(PathRequest
                               .toStaticResources()
                               .atCommonLocations())
                       .permitAll()
                       .requestMatchers("/book/{bookId}/testResults")
                       .authenticated()
                       .anyRequest().permitAll())
               .formLogin(login ->login
                       .loginPage("/login")
                       .failureHandler(simpleUrlAuthenticationFailureHandler())
                       .defaultSuccessUrl("/")
                       .permitAll())
                        .oauth2Login(oauth2 -> oauth2
                        .loginPage("/login")
                        .userInfoEndpoint(userInfo -> userInfo
                                .oidcUserService(oidcUserService())))
                .build();

    }

    SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler(){
       SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler();
       handler.setDefaultFailureUrl("/login?error");
       handler.setAllowSessionCreation(true);
       return handler;
    }

    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService(){
         return userRequest ->{

             String email = userRequest.getIdToken().getEmail();

             User user = userService.findByUsername(email);

             if(user==null){
                user =  userService.registerOauthUser(email);
             }

             return new DefaultOidcUser(List.of(),userRequest.getIdToken());
         };
    }
}

And this is my thymeleaf-html header where I first check if the user is authenticated and then have to contact him depending on the authentication type.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml" lang="eng">
<head>
    <link rel="stylesheet" type="text/css" href="/css/header-styles.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">


    <title>Java Quiz Hub</title>
</head>
<body>

<header class="site-header">
    <nav>
        <div class="nav-item"><a th:href="@{/}">Java Quiz Hub</a></div>
        <div class="nav-item"><a href="/books">Books</a></div>
        <div class="nav-item"><a href="#">About</a></div>
        <div class="nav-item"><a href="#">Contact</a></div>
        <div class="nav-item">
           <span sec:authorize="isAuthenticated()" class="login-part">
              <a href="/user/myProfile"
                 th:text="${#authentication.principal.getEmail() != null ? #authentication.principal.getEmail() : #authentication.principal.username}">
</a>

            </span>
            <span th:if="${#authentication == null}" class="login-part">
                <a href="/login" style="color: white; text-decoration: none;">Login</a>
            </span>
        </div>
    </nav>
</header>


<div class="content">

</div>

</body>
</html>

I would be very grateful if you could help me with my problem. Also, if there is something wrong in my code with the Oauth 2.0 setting, please correct me and point out the error.

I also have an additional question about Oauth + OpenIdConnect in general. How to properly save users who authenticated this way for the first time. Should I register them in the application? Should I leave them without a password? Or correctly add OidcUser to the inheritance of my UserDetails. I don’t understand at all what is customary to do in these cases, and I can’t find the necessary information on this topic.

0

There are 0 answers