Interface Relogin
Relogin
When a user's session has expired and the user tries to navigate to a protected resource, typical authentication systems will redirect the user to a login page. With Ajax systems such as Smart GWT, this attempted redirect may happen in response to background data operations such as a form trying to save. In this case, the form perceives the login page as a malformed response and displays a warning, and the login page is never displayed to the user.The ideal handling of this scenario is that the form's attempt to save is "suspended" while the user re-authenticates, then is completed normally. Smart GWT makes it easy to implement this ideal handling without having to implement session timeout handling in every codepath that contacts the server, by providing central notification of session timeout, and the ability to re-send a transaction that encountered session timeout.
Detecting session timeout
To enable Smart GWT to detect that session timeout has occurred, a special marker needs to
be added to the HTTP response that is sent when a user's session has timed out. This is
called the loginRequiredMarker
.
If your authentication system will redirect to a login page when a user's session is timed
out, it's sufficient to simply embed the loginRequiredMarker
in the login page.
The
loginRequiredMarker
is valid HTML and will have no effect on the behavior or
appearance of the page. The loginRequiredMarker
is found in
docs/loginRequiredMarker.html
in your SDK. Simply copy the contents of this file verbatim into your login page anywhere
inside the <body> tag; it does not need to be customized in any way for your application.
The HTML snippet in loginRequiredMarker.html consists of two parts:
- It includes the
loginRequiredMarker
. Responses to standardxmlHttpRequest transport
RPC requests will be scanned for this marker and kick off theloginRequired flow
automatically. - For
hiddenFrame transport
request, it also includes some JavaScript to explicitly notify the RPCManager in the Smart GWT app running in the parent frame or opener window that login is required.
If it's a problem to modify the login page (even with a marker that has no effect on
appearance or behavior), see if you can configure your authentication system to return a
special response specifically for background requests for data. By default, when using the
Smart GWT Server Framework, all such requests go to the actionURL
and
include an HTTP query parameter "isc_rpc=1"; various authentication systems can be
configured to detect these requests and handle them separately. One approach is to simply
copy loginRequiredMarker.html into your application in an area not protected by
authentication and redirect to it when a background data request with an expired session is
detected.
Handling session timeout
When Smart GWT detects the loginRequiredMarker
, the transaction that
encountered session timeout is put on hold, and
the RPCManager LoginRequired event is raised.
At this point you have a few options:
- Leave the Smart GWT application and take the user to the login page, by simply doing a
window.location.replace(myLoginURL)
, the simplest but least user friendly option. - Open a new browser window that goes to your plain HTML login form (or offer a link that
opens such a browser window), using a modal dialog in the application page that prompts the
user to login before continuing, then re-send the intercepted transaction
(
RPCManager.resendTransaction()
when the user indicates he has logged in. This is simple, does not drop context, but is not seamless. - Use a Smart GWT interface, typically a DynamicForm in a Window, to collect credentials,
perform login as a background RPC, and on success re-send the intercepted transaction
(
RPCManager.resendTransaction()
.
To relogin against any system that can accept credentials as an HTTP POST:
- when the LoginRequired event is raised, show a login form in a modal dialog. The
LoginWindow
component is a simple version of this, or you can create your own - when the user enters credentials, POST them using code like the following:
RPCRequest request = new RPCRequest(); request.setContainsCredentials(true); request.setActionURL(credentialsURL); request.setUseSimpleHttp(true); request.setShowPrompt(false); Map<String,String> params = new HashMap<String,String>(); // adjust parameter names to match your authentication system params.put("j_username",username); params.put("j_password",password); request.setParams(params); RPCManager.sendRequest(request,new RPCCallback(){ public void execute(RPCResponse response, Object rawData, RPCRequest request) { if (response.getStatus() == RPCResponse.STATUS_SUCCESS) { // get rid of login window RPCManager.resendTransaction(); } else if (response.getStatus() == RPCResponse.STATUS_LOGIN_INCORRECT) { // show an error in the login window } } });
- configure your authentication system to send back the loginSuccessMarker as part of a successful login response, and the loginRequiredMarker as part of a failed login response
loginSuccessMarker
file itself as a
protected resource. The loginSuccessMarker
is found in
docs/loginSuccessMarker.html
in your SDK.
Authentication via background Smart GWT server RPC/DMI
If you are using the Smart GWT Java server and your authentication system allows you to mark a user as authenticated from Java, you can perform a normal RPC or DMI with the credentials gathered from the user and send back success or failure indications as normal RPC or DMI responses. This can be useful if, in addition to logging in, you want to send back additional data.
Advanced: concurrency
If, after loginRequired() has fired and before the user has re-authenticated, you send
additional RPCs to protected URLs, you will get additional loginRequired() notifications. This
may happen to applications that poll for data or periodically save without user action. You
may wish to avoid this by setting an application-specific flag to avoid firing requests during
the relogin process. However, you must ultimately either
resend
or discard
every transaction for which loginRequired() fires, or you will have a memory leak due to
suspended transactions.
Note also that there is no requirement that the relogin process blocks user interaction. Applications that access multiple services may choose to simply show an unobtrusive error indication such that the user can log back in at his leisure, or even log the user back in automatically.
- See Also:
-
com.smartgwt.client.rpc.RPCManager#loginRequired
com.smartgwt.client.rpc.RPCManager#credentialsURL
com.smartgwt.client.rpc.RPCManager#loginStatusCodeMarker
com.smartgwt.client.rpc.RPCManager#loginRequiredMarker
com.smartgwt.client.rpc.RPCManager#loginSuccessMarker
com.smartgwt.client.rpc.RPCManager#maxLoginAttemptsExceededMarker
com.smartgwt.client.rpc.RPCManager#reloginCommFailureMessage
RPCRequest.getContainsCredentials()