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);