package com.smartgwt.client.docs; /** * <h3>Relogin</h3> * 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. * <P> * 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 <i>without</i> 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. * <P> * <h3>Detecting session timeout</h3> * <P> * 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 <code>loginRequiredMarker</code>. * <P> * 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 <code>loginRequiredMarker</code> in the login page. The * <code>loginRequiredMarker</code> is valid HTML and will have no effect on the behavior or * appearance of the page. The <code>loginRequiredMarker</code> 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. * <P> * 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 {@link com.smartgwt.client.rpc.RPCManager#actionURL 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. * <P> * <h3>Handling session timeout</h3> * <P> * When Smart GWT detects the <code>loginRequiredMarker</code>, 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: * <ol> * * <li> Leave the Smart GWT application and take the user to the login page, by simply doing a * <code>window.location.replace(<i>myLoginURL</i>)</code>, the simplest but least user friendly * option. * * <li> 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 * ({@link com.smartgwt.client.rpc.RPCManager#resendTransaction RPCManager.resendTransaction} when the user indicates he * has logged in. * This is simple, does not drop context, but is not seamless. * * <li> 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 * ({@link com.smartgwt.client.rpc.RPCManager#resendTransaction RPCManager.resendTransaction}. * * </ol> * <B>Authentication via background RPC form POST</B> * * <span class="smartgwt"> * * <P> * To relogin against any system that can accept credentials as an HTTP POST: * <ol> * <li> 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 * <li> when the user enters credentials, POST them using code like the following: * <pre> * 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",<i>username</i>); * params.put("j_password",<i>password</i>); * 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 * } * } * }); * </pre> * <li> 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 * </ol> * If your authentication system can accept POST'd credentials at any URL it protects, the last * step may be as simple as configuring the loginSuccessMarker file itself as a protected * resource (isomorphic/login/loginSuccess.html). * * </span> * <P> * <B>Authentication via background Smart GWT server RPC/DMI</B> * <P> * 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. * <P> * <B>Advanced: concurrency</B> * <P> * 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 * {@link com.smartgwt.client.rpc.RPCManager#resendTransaction resend} or {@link * com.smartgwt.client.rpc.RPCManager#clearTransaction discard} * every transaction for which loginRequired() fires, or you will have a memory leak due to * suspended transactions. * <P> * 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 com.smartgwt.client.rpc.RPCManager#credentialsURL * @see com.smartgwt.client.rpc.RPCManager#loginRequired * @see com.smartgwt.client.rpc.RPCRequest#getContainsCredentials */ public interface Relogin { }