I am using keycloak(4.3.0) openid-connect flow. For my client app, I am using:
public class AuthenticationTest {
public static void main(String[] args) {
final String KEYCLOAK_JSON = Constants.KC_CONFIG_JSON_PATH;
InputStream config = Thread.currentThread().getContextClassLoader().getResourceAsStream(KEYCLOAK_JSON);
KeycloakInstalled keycloak;
try {
keycloak = new KeycloakInstalled(config);
config.close();
keycloak.loginDesktop();
AccessToken token = keycloak.getToken();
System.out.printf("UserId: %s%n", token.getSubject());
System.out.printf("Username: %s%n", token.getPreferredUsername());
System.out.printf("Email: %s%n", token.getEmail());
System.out.println(keycloak.getTokenString());
System.in.read();
} catch (IOException | VerificationException | OAuthErrorException | URISyntaxException | HttpFailure
| InterruptedException e) {
e.printStackTrace();
}
}
}
I have referred the example mentioned here: https://gist.github.com/thomasdarimont/ca16080145d226e50628d5696ffb9508
First time I launch the application and login, I get
"Login Successful.You may close this browser window and go back to
your console application."
However, if I launch second instance of my application/ relaunch my application even without closing the previous browser window , still the login page appears instead of you are already logged in message.
(The new login page is appearing in a new tab on the same window as the first login page, so it is not an issue of failure to maintain state across different windows. Also I have tried relaunching the app withing 20 seconds so it does not seem t be an issue of timeout either)
Browser: Firefox, chrome.
Any idea what I am doing wrong. Expectation is that browser must maintain a keycloak session for the same user until closed for at least a few minutes.
NOTE: I did not face this issue in Keycloak 3.4.3. But it started coming on 4.1.0 and 4.3.0
I see follwing difference in cookies on 3.4.3 and 4.x:
3.4.3: (same whther first login or subsequent login)
4.x First time login:
4.x Subsequent login: (an addition KC_RESTART cookie is seen)
Related
I have a spring-boot web application to be distributed as jar file. The code to start the application is as follows:
private static ConfigurableApplicationContext ctx;
public static void main(String[] args){
if(ctx == null) {
ctx = SpringApplication.run(MyApplication.class, args);
}
try {
openHomePage("http://localhost:8090/");
}catch(Exception e) {
logger.error("Error occured starting the application: ", e);
ctx.close();
}
}
private static void openHomePage(String url) throws IOException, URISyntaxException {
if(Desktop.isDesktopSupported()) {
URI homePage = new URI(url);
Desktop.getDesktop().browse(homePage);
}else {
Runtime runtime = Runtime.getRuntime();
runtime.exec(new String[]{"cmd", "/c","start chrome " + url});
}
}
which opens the home page in Chrome, both when I run it from Eclipse and by double clicking on the jar file.
The problem is when I start the application from the jar file and close the browser tab, the application continues to run in JVM and I have to kill it from the task manager manually which is annoying. If I don't kill the JVM and double click on the jar file again, then the application doesn't start automatically as it does the first time, and I have to manually open a new browser tab and type http://localhost:8090/ in order to use the application.
Is it possible to kill every process after user closes the browser tab so that when they click on the jar file next time they need to use the application, a fresh browser tab opens automatically?
Thanks in advance..
SOLUTION
This might not be the best solution but it works a treat.
*Step 1 - Send heartbeats from the browser
var heartBeatIntervals = null;
$( document ).ready(function() {
//this ajax call will be fired every 2 seconds as long as the browser tab stays open.
// the time intervals can of course be modified
heartBeatIntervals = setInterval(() => {
$.ajax({
type:'POST',
url: 'http://localhost:8090/MyController/checkHeartbeats'
})
}, 2*1000);
});
*Step 2 - Handle the heartbeats in the server
#Controller
#RequestMapping("/MyController")
public class MyController {
//declare an instance variable to store the number of missed heartbeats
private int missedHeartbeats = 0;
//reset the counter to 0 upon receiving the heartbeats
#PostMapping("/checkHeartbeats")
public void checkHeartbeats() {
missedHeartbeats = 0;
}
//increase the missedHeartbeats by one every 3 seconds - or whatever
#Scheduled(fixedRate = 3000)
public void schedule() {
missedHeartbeats++;
//check how many heartbeats are missed and if it reaches to a certain value
if(missedHeartbeats > 5) {
//terminate the JVM (also terminates the servlet context in Eclipse)
System.exit(0);
}
}
}
*Step - 3 Enable scheduling
In order to use any scheduling in spring-boot application you need to add #EnableScheduling annotation in your class where your main method resides.
And that's it.
There's a stop button in Eclipse. And in case it can't be used:
You can send something from javascript to your server continiously and when server haven't recieved it for 1 sec, which means the web page was closed, stop itself.
Solution 1
Use a method in any #Controller to handle heartbeat requests.
Store the most recent heartbeat time in a static field of any class, the initial value could be 0 or -1 indicating the web page has not been opened yet.
Use a #Scheduled task to retrive last heartbeat time and compare with current time. schedule the task once per 2 second or whatever. https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/scheduling.html#scheduling-annotation-support
Stop JVM if needed, maybe by System.exit(0).
Solution 2
It would be easier if you can add a Close button on webpage. being clicked, it signals the server to stop, and afterwards it closes the web page itself. https://stackoverflow.com/a/18776480/9399618
I've a webapp running on TOMCAT 7.0.5 - JDK 1.7 - and connecting to SQL Server 2012.
The hibernate version is 4.3.5. Browser used is IE 11.0.
The issue Is I have a webpage: A normal FORM submit (submit.jsp). It shows a readonly page (submitConfirm.jsp) and has two buttons.
Submit - Saves the application and redirects the page to the home page to start subscription again
Print - opens a new tab via javascript to print a PDF form that likely takes 2 to 5 seconds to render in a "new" tab.
The submit button is disabled by defualt and enabled only when user clicks on the PRINT Button. While the item is still rendering If someone clicks on Continue button - all actions perform well and at the I get both the print and subscriptions saved.
The next subscriptions entered would throw a http 500 error indicating the "Connection is already closed".
I use the Standard HibernateUtil paradigm to begin/end/commit/rollback transactions.
The models are all XML based (not entity decorator based).
For normal workflows where if the user waits till the PDF is rendered all is fine.
But If the user is pressing the button of continue - Seems there is an issue.
Attached is the screen-grab of the error is someone finds it useful provide some hints.
Based on the user feedback (the concerned method):
public String reportSessionId(String userId) throws InfrastructureException {
String sid = null;
try {
sid = (String) HibernateUtil.getSession()
.getNamedQuery("com.ttsme.ims.model.IMSUser.reportSessionId")
.setString("userId", userId).uniqueResult();
}
catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
catch (Exception exp)
{
exp.printStackTrace();
}
return sid;
}
Configurations:
OS : Ubuntu
Java version : 8
Selenium : 3.8.0
ChromeDriver : 2.33
Chrome version : 60
I'm automating an application where i have to login in a system using Social media
After entering mobile number it ask for password and there social media icon. If i click lets say google plus, it opens google plus login window then I have to provide credential then the window get closed automatically and user gets login. As shown here
My issue is, after logout from my application if i again try to login using google plus then it perform automatic login (second time it won't ask for google plus credentials as google plus session cookies are there)
So in my script I'm trying to delete all cookies after first test but it is not working code line I've tried :
driver.manage().deleteAllCookies();
For reference complete test look like :
#Test
public void newUserRegistration_GooglePlus_ForAlreadyExistEmail() throws IOException, InterruptedException, JSONException
{
LogoutAnalyzer.checkLogout();
loginpage.sendUsername(excel.getCellData(6, 18, 1));
CommonMethods.waitUntilLoaderGetInvisible(driver);
TakeScreenshot.passedScreenShot("Username");
LogWriter.logger.info("Mobile number has entered");
loginpage.clickSubmitButton();
CommonMethods.waitUntilLoaderGetInvisible(driver);
LogWriter.logger.info("Submit button clicked");
if(loginpage.otpTextbox.size()>0)
{
String OTP = otpreader.getOTP(excel.getCellData(6, 18, 1));
LogWriter.logger.info("Got the OTP via API call OTP is "+OTP);
loginpage.enterOTP(OTP);
TakeScreenshot.passedScreenShot("OTP_Entered");
LogWriter.logger.info("OTP Entered");
loginpage.clickConfirmCodeButton();
CommonMethods.waitUntilLoaderGetInvisible(driver);
LogWriter.logger.info("Submit button clicked");
TakeScreenshot.passedScreenShot("Profile_Info");
loginpage.clickGooglePlusIcon();
Thread.sleep(5000);
LogWriter.logger.info("Switch to Google Plus window");
CommonMethods.switchWindow(driver);
CommonMethods.waitForElementVisibility(driver, new RCONGooglePlusPage(driver).usernameField);
TakeScreenshot.passedScreenShot("Google Window");
sm_helper.googlePlusLogin(excel.getCellData(6, 18, 2), excel.getCellData(6, 18, 3));
CommonMethods.switchToParentWindow(driver);
LogWriter.logger.info("Switched back to RContacts window");
CommonMethods.waitUntilLoaderGetInvisible(driver);
Assert.assertEquals(loginpage.getValidationMessage(), PropertyFileReader.getProperty("emailAlreadyExistMessage"));
LogWriter.logger.info(PropertyFileReader.getProperty("emailAlreadyExistMessage"));
}
else
{
TakeScreenshot.passedScreenShot("Already_registered_User");
LogWriter.logger.info("This user is already a registered user");
}
driver.manage().deleteAllCookies();
LogWriter.logger.info("all cookies deleted");
}
I'm using the embedded browser.
import org.eclipse.swt.browser.Browser;
.....
final Browser g11_embedded_browser = new Browser(g11_capture_script, SWT.NONE);
g11_embedded_browser.setBounds(0, 0, 1000, 260);
g11_embedded_browser.setVisible(true);
...........
try {
uri = new URI("http://127.0.0.1:" + g11_txt_PATH_portnumber.getText());
} catch (URISyntaxException e1) {
System.out.println("failed setting uri");
e1.printStackTrace();
}
System.out.println("uri=" + uri.toString());
try {
url = uri.toURL();
The full url is: http://127.0.0.1:6500
The C program listening on 6500 sometimes responds first time. At other times it takes 2 attempts.
I believe it returns a 204 when the connection fails.
My questions in the hope someone can point me in the right direction are:
Is there any way I can detect the 204? It displays nothing in the browser as it is deemed a successful reply.
Any clue as to why the 204 as the C program never issues a 204 when the request comes from any browser on any OS, just when from the embedded browser.
Note:
The browser displays an internet page before the localhost request so it isn't an embedded browser start up issue. Tried it with and without that.
Tried interleaving requests to the C program from browsers and the Java browser but 100% success externally and about 50% failures from Java on first attempt. Occasionally needs three or even 4 attempts but always works in the end.
A 204 is "204 - The server successfully processed the request, but is not returning any content. Usually used as a response to a successful delete request." However the localhost call is a request for the display of a simple form.
I am implementing FB in one of my app.I am using jar 0.8.25. Its working fine on all simulators from 5 to 7.1.And for devices works only for OS 5 and 6 but not working on device 7 and 7.1.For OS 7 after log in success it remains on FB page it doesn't redirect back. and when i press back button, i get error encountered unable to refresh access token with try again button.
When analyzing on console it never finds access token single time for OS 7.while for 5 and 6 its working perfectly.
Please tell what may cause the issue.
Thanks,
This isn't a solution to your specific problem. I mentioned in the comments that I'm using an interface. So I'm posting here as its too much for the comment section. It is also not the COMPLETE solution, you will need to handle the flow and expired tokens, this is just to show you the logic of how I did this.
For my interface I open a browserfield to the Oauth url:
https://www.facebook.com/dialog/oauth?client_id=<APP_ID>&response_type=token&redirect_uri=http://www.facebook.com/connect/login_success.html&scope=publish_actions
And I add a listener to this browser to listen for the redirects after login. Once you have the access token, you should persist it and close the browserfield.
private class OAuthScreen extends MainScreen
{
BrowserField browser_field;
LoadingDialog loading_dialog;
public OAuthScreen(final Command task)
{
super(VERTICAL_SCROLL | HORIZONTAL_SCROLL);
BrowserFieldConfig browserConfig = new BrowserFieldConfig();
browserConfig.setProperty(BrowserFieldConfig.VIEWPORT_WIDTH, new Integer(Display.getWidth()));
browser_field = new BrowserField(browserConfig);
browser_field.addListener(new BrowserFieldListener()
{
public void documentCreated(BrowserField browserField, ScriptEngine scriptEngine, Document document) throws Exception
{
int index = browserField.getDocumentUrl().indexOf("#access_token=");
if (index == -1)
{
super.documentCreated(browserField, scriptEngine, document);
}
else
{
access_token = browserField.getDocumentUrl().substring(index + "#access_token=".length(), browserField.getDocumentUrl().indexOf("&"));
PersistentObject store = PersistentStore.getPersistentObject(STORE_KEY);
FacebookTokens store_tokens = new FacebookTokens();
store_tokens.access_token = access_token;
store.setContents(store_tokens);
store.commit();
if (task != null) task.execute();
OAuthScreen.this.close();
}
}
public void documentLoaded(BrowserField browserField, Document document) throws Exception
{
super.documentLoaded(browserField, document);
loading_dialog.close();
}
});
// whatever loading dialog you want, this sometimes takes a while to open
loading_dialog = LoadingDialog.push(loading_field);
add(browser_field);
browser_field.requestContent("https://www.facebook.com/dialog/oauth?client_id="+APP_ID+"&response_type=token&redirect_uri=http://www.facebook.com/connect/login_success.html&scope=publish_actions");
}
}
The callback task is just for if I want to perform a call directly after login.
Now just perform API calls as you need them. API methods here https://developers.facebook.com/docs/graph-api/reference/v2.0/
Methods that require the access token, should have it appended to the url such as, https://graph.facebook.com/me/feed?access_token=" + access_token
Be aware that clearing your access token won't clear the token stored in the browser field. And will mean that you can't login next time (because the browser is still logged in).
So if you want to logout you need to open this link in a browserfield before clearing your local access token "https://www.facebook.com/logout.php?next=http://www.facebook.com/connect/login_success.html&access_token=" + access_token
Clearing the cookies of the browser should suffice, but I haven't found a way to do this.