Why is my SecurityContextHolder resetting after navigating to the new UI in my vaadin application?

54 Views Asked by At

My SecurityContextHolder reset after navigating to the new UI or refresh the page in my vaadin application. I have used the Firebase authentication successfully using JavaScript and then I got the token and Firebase user ID using the login method using ClientCallable annotation. Then I set the Authentication by getting the new authentication. after refresh the page or navigating to other view authentication log message is like below,

Principal : anonymousUser Credentials : Auth : AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=5E5D572F6FF1ECAF2EC27CD086ACB6F6], Granted Authorities=[ROLE_ANONYMOUS]]

Login class :

@AnonymousAllowed
@PageTitle("Login")
@Route(value = "login")
@JsModule("./JavaScripts/firebase.js")
public class LoginView extends VerticalLayout implements BeforeEnterObserver{
  private static final String OAUTH_URL = "/oauth2/authorization/google";
  private final FirebaseService firebase;
  public LoginView(FirebaseService firebaseService){
    this.firebase = firebaseService;
    // Header
    Div header = new Div();
    header.setText("Welcome to File Fortress");
    header.getStyle().set("font-size", "24px");
    add(header);

    // Slogan
    Div slogan = new Div();
    slogan.setText("LAN Exam File Transfer System");
    slogan.getStyle().set("font-size", "18px");
    add(slogan);

    // Description
    Div description = new Div();
    description.setText("Login with Your Google Account to Continue");
    description.getStyle().set("font-size", "16px");
    add(description);

    // Login button
    Button loginButton = new Button("Login with Google");
    loginButton.setTooltipText("You Can Sign In to Application using your Google Account");
    loginButton.addClassName("login-button");
    loginButton.addClickListener(event -> {
//     UI.getCurrent().getPage().setLocation(OAUTH_URL);
        UI.getCurrent().getPage().executeJs("ns.googleSignInPopup($0)", this);
    });

    add(loginButton);

    // Styling
    getStyle().set("padding", "20px");
    setAlignItems(FlexComponent.Alignment.CENTER);
}

@Override
public void beforeEnter(BeforeEnterEvent event) {
    if(SecurityContextHolder.getContext().getAuthentication().isAuthenticated())
        UI.getCurrent().navigate(AboutView.class);
}
@ClientCallable
public void login(String token, String uid){
    System.out.println(token);
    User.getInstance().init(uid,token);
    try {
        // Validate the token at Firebase server  first and create
        Authentication authentication = firebase.login(token);
        // Save the authentication to context
        SecurityContextHolder.getContext().setAuthentication(authentication);
    } catch (FirebaseAuthException e) {
        throw new RuntimeException("Invalid token!");
    }
}


}

FirebaseService class :

@Service
public class FirebaseService {

private FirebaseApp app;
@PostConstruct
void init() {
    try {
        FileInputStream serviceAccount = new FileInputStream("serviceAccountKey.json");

        FirebaseOptions options = new FirebaseOptions.Builder()
                .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                .build();
        FirebaseApp.initializeApp(options);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

}

public UserRecord findUserByEmail(String username) throws FirebaseAuthException {
    return FirebaseAuth.getInstance().getUserByEmail(username);
}

public Authentication login(String token) throws FirebaseAuthException {
    boolean checkRevoked = true;
    FirebaseToken firebaseToken = FirebaseAuth.getInstance().verifyIdToken(token, checkRevoked);
    // Note, before important actions, the token should be re-validate,
    // it could be revoked or the user could be removed altogether,
    // during their session

    return new Authentication() {
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            Collection<GrantedAuthority> updatedAuthorities = new ArrayList<>();
            updatedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            return updatedAuthorities;
        }

        @Override
        public Object getCredentials() {
            return token;
        }

        @Override
        public Object getDetails() {
            return firebaseToken;
        }

        @Override
        public Object getPrincipal() {
            return firebaseToken.getUid();
        }

        @Override
        public boolean isAuthenticated() {
            return true;
        }

        @Override
        public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {

        }

        @Override
        public String getName() {
            return firebaseToken.getName();
        }
    };
}
}

I want to Save the authentication to SecurityContextHolder but it has to be the same Authentication until the user is logged out.

 SecurityContextHolder.getContext().setAuthentication(authentication);
0

There are 0 best solutions below