After application logout click on back button enter to application page in play framework - scala

I added session using play framework. Session works fine,but after logout page redirected to index page(login page).Then click on back or forward button again enters to home page. I have started new session on logout,then also it enters to homw page.How to show the same index page on back or forward button click?
def login = Action {
{ implicit request =>
val email = request.body.asFormUrlEncoded.get("email")(0)
val password = request.body.asFormUrlEncoded.get("password")(0)
loginForm.bindFromRequest.fold(
errors => BadRequest(html.index(emailForm,errors,"Please enter valid username password")),
contact => Redirect(routes.Application.home).withSession("email" -> email,"password" -> password)
)
}
}
def home = Action { request =>
request.session.get("email").map{ user => Ok(views.html.home())
}.getOrElse{
Ok(views.html.index(emailForm,loginForm,""))
}
}
def logout = Action {
Redirect(routes.Application.index).withNewSession
}

To prevent browser back/forward buttons from navigating to a logged-in screen, you need to have two mechanisms in place:
Tell browsers that they should always hit your server for any of the web pages that sit behind your login screen.
Decorate every action that serves back one of your secured web pages with a check to see whether the person making the request has logged in. The check should then serve back the index page if they don't have anything within their cookie that conveys their identity.
The first of these can be achieved by getting your actions to set the following header in the HTTP response:
Cache-Control: no-cache
From this tutorial:
no-cache — forces caches to submit the request to the origin server for validation before releasing a cached copy, every time. This is useful to assure that authentication is respected (in combination with public), or to maintain rigid freshness, without sacrificing all of the benefits of caching.
You may already have the second mechanism in place. If not, you'll have to write an action that performs the check.
The recommended way to then apply both of these mechanisms to all of your pages would be to use action composition.

Related

Keycloak : implement "reset password" (as admin) flow same as "forgot password" (as user)

I would like to implement this authentication flow in Keycloak:
A user creates an account by typing only his email
The user is logged in and can access my service
2'. At the same time, an email is sent to him, allowing him to "finalize" his account
The user leaves his session -> to reuse my service, he must click in the received email
By clicking in the received email, the user defines his first password
The user is then logged in automatically (without going through a login page).
The objective of this flow is to be the simplest, to hook users who are not used to webapps.
The implementation I would do:
Create an account without password request: I customize the Keycloak Registration flow by disabling the Password Validation and Profile Validation rules
Programmatically, in my webapp, at the first connection of a user, via the REST Admin API, I trigger the email action UPDATE_PASSWORD
I get something that works, but:
A. The link received by email redirects to an intermediary page confirming the execution of actions ("Perform the following action (s)") - (similar to Keycloak Implement Reset password flow same as forgot password flow)
B. The user is then redirected to a login page, and not directly connected to the application.
When, as a normal user, I trigger a reset password request (through 'forget password' feature), the process is the one I want: by clicking on the email link, I go directly to the page allowing me to enter and confirm a new password, then I'm authenticated.
My question: Do you see a way to implement this 'simplified' flow?
My keycloak version : 11.0.2
Thank you !
I could remove the "info.ftl" page display, customizing the "ExecuteActionsActionTokenHandler", as explained here :
action-token-spi
You have to create a file :
src/main/resources/META-INF/services/org.keycloak.authentication.actiontoken.ActionTokenHandlerFactory
containing the name of the class you want to use instead :
com.example.ExecuteActionTokenHandlerFactory
Then you create that class com.example.ExecuteActionTokenHandlerFactory with the following code :
public class ExecuteActionTokenHandlerFactory extends ExecuteActionsActionTokenHandler {
#Override
public Response handleToken(ExecuteActionsActionToken token, ActionTokenContext<ExecuteActionsActionToken> tokenContext) {
AuthenticationSessionModel authSession = tokenContext.getAuthenticationSession();
String redirectUri = RedirectUtils.verifyRedirectUri(tokenContext.getUriInfo(), token.getRedirectUri(),
tokenContext.getRealm(), authSession.getClient());
if (redirectUri != null) {
authSession.setAuthNote(AuthenticationManager.SET_REDIRECT_URI_AFTER_REQUIRED_ACTIONS, "true");
authSession.setRedirectUri(redirectUri);
authSession.setClientNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUri);
}
token.getRequiredActions().stream().forEach(authSession::addRequiredAction);
UserModel user = tokenContext.getAuthenticationSession().getAuthenticatedUser();
// verify user email as we know it is valid as this entry point would never have gotten here.
user.setEmailVerified(true);
String nextAction = AuthenticationManager.nextRequiredAction(tokenContext.getSession(), authSession, tokenContext.getClientConnection(), tokenContext.getRequest(), tokenContext.getUriInfo(), tokenContext.getEvent());
return AuthenticationManager.redirectToRequiredActions(tokenContext.getSession(), tokenContext.getRealm(), authSession, tokenContext.getUriInfo(), nextAction);
}
}
Actually it is the same implementation as the upper class, except we removed the following part :
if (tokenContext.isAuthenticationSessionFresh()) {
...
}
which means that if the user did not have a session, which happens when the user is reseting his password, he is redirected to that "info.ftl" page.
As a workaround for problem A, I customize info.ftl template page. I add an ugly inline script to click on the link, redirecting automatically to the update password page.
<#import "template.ftl" as layout>
(...)
<#elseif actionUri?has_content>
<p><a id="yolo" href="${actionUri}">${kcSanitize(msg("proceedWithAction"))?no_esc}</a></p>
<script>document.getElementById('yolo').click()</script>
(...)
It'll do the job until I found a cleaner solution.
At the moment, B problem remains.

GWT: A way to cancel PlaceChangeEvent?

I'm using Activity/Place in my GWT project, if current user is not logged in, when he navigates to some Place, the user will be redirect to login page, if the user has logged in, then he will be taken to that Place. How to implement this logic efficiently?
I tried to hook PlaceChangeRequestEvent:
eventBus.addHandler(PlaceChangeRequestEvent.TYPE,new PlaceChangeRequestEvent.Handler() {
#Override
public void onPlaceChangeRequest(PlaceChangeRequestEvent event) {
Place newPlace = event.getNewPlace();
if (newPlace instanceof MyProtectedPlace && userNotLoggedIn()) {
event.goTo(new LoginPlace());
}
}
});
Unfortunately it does not work since the ongoing request for MyProtectedPlace is not cancelled.
Yes I could check this when user are about to navigation away from current place, but this will not be efficient as the check logic will scattered throughout the program.
Thanks.
You can do it a little bit differently I think. Let's say that you want a place called SecuredPlace to be accessible only after login. You have a corresponding SecuredActivity.
What you can do is, when you start your SecuredActivity, you check if your user is logged in. If not you do placeController.goTo(new LoginPlace ()).
If the user is logged in then you continue. As the start is called by the framework there is no way to skip this step which in my opinion makes it secured enough.
But you should implement your security on network calls to your backend not on places. Every time you call the backend, you check that user is authenticated and has the right credentials. If not you can intercept the callback, check that it is a 403 error and then redirect automatically to your login page. Because if your backend calls are not secured, securing your places is useless.

How to redirect the user to a custom page when user click "Connect to QuickBooks" button?

So Intuit charges for each active connections to QuickBooks. Therefore, I want to restrict the QuickBooks functionality in my application to premium users only.
Ideally when any user clicks the "Connect to QuickBooks" button and my RequestOAuthToken http handler is called, I want to check if the user is allowed to use QuickBooks. If that is the case, then the normal OAuth flow continue. If the user is NOT allowed, then I want to redirect the user to the upgrade page of my app.
Given that the "Connect to QuickBooks" button opens a new window (at least on desktop, I haven't tried on phone/tablets), the window should get closed, and the main window (my app) should redirect the user to the right page. And actually this is exactly what happens if the normal OAuth flow completes.
Now, I have tried a few different approaches but I couldn't get it working.
1) In my RequestOAuthToken, return a HTTP redirect to the plan page
2) In my RequestOAuthToken, return an html page with javascript logic to redirect to page
3) In my RequestOAuthToken, return HTTP redirect to a page with javascript logic to redirect to page
4) I haven't tried that one but could I somehow intercept the javascript click handler on the Intuit button. I'm not sure if that is an accepted practice.
Here is the piece a javascript I grabbed from the .Net sample:
try
{
var parentlocation = window.parent.opener.location.hostname;
var currentlocation = window.location.hostname;
if (parentlocation != currentlocation)
{
window.location = plansUrl;
}
else
{
window.opener.location.href = window.opener.location.href;
window.close();
}
}
catch (e)
{
window.location = plansUrl;
}
Help me out please.
I don't think you'll be able to do exactly what you're asking, but you can probably come close by taking a different approach.
Rather than trying to redirect them after they click the button, why not try to redirect them before they click it? e.g. when they try to get to the page that has the "Connect to QuickBooks" button it, check if they are a premium user there, and redirect them if they are not.
I don't think you'll be able to redirect them after they click the button because once they click that button, they get kicked over to Intuit's website and it's beyond your control at that point.
Clement, Keith has provided the answer we would want you to pursue. You may not alter the behavior of the Connect To QuickBooks button. It must be used as described in our documentation. Providing a link to a page that shows the Connect To QuickBooks buttons for your premium users and an upgrade message to non-premium users is the way to go.
I highly recommend that you visit http://docs.developer.intuit.com/0025_Intuit_Anywhere/0010_Getting_Started/0040_Publishing_Your_App and review all of the documentation there. If you develop with our guidelines and requirements in mind it will speed up the review process.
Tony Purmal
Developer Relations Engineer
Intuit Partner Platform

Redirect after user has logged in

I'm pretty new to Angular, and right now I'm just trying to get all my routes set up and working as I'd like.
Setup:
When a user navigates to certain pages (/settings for this example) the app should check if there is a user already logged in. If there is continue as usual. Otherwise the user should go to the login page (/login).
What I'd like:
After the user has successfully logged in they should go to the page they were originally trying to get to (/settings)
My question:
Is there an "Angular way" to remember where the user was trying to go to?
Relevant code:
app.js
.when('/settings', {
templateUrl: '/views/auth/settings.html',
controller: 'SettingsCtrl',
resolve: {
currentUser: function($q, $location, Auth) {
var deferred = $q.defer();
var noUser = function() {
//remember where the user was trying to go
$location.path("/login")
};
Auth.checkLogin(function() {
if (Auth.currentUser()) {
deferred.resolve(Auth.currentUser());
} else {
deferred.reject(noUser());
}
});
return deferred.promise;
}
}
})
login.js
$scope.submit = function() {
if(!$scope.logInForm.$invalid) {
Auth.login($scope.login, $scope.password, $scope.remember_me)
//go to the page the user was trying to get to
}
};
Much thanks to John Lindquist for the video which got me this far.
First off, you do not want to redirect the user to a login page.
An ideal flow in a single page web app is as follows:
A user visits a web site. The web site replies with the static assets for the
angular app at the specific route (e.g. /profile/edit).
The controller (for the given route) makes a call to an API using $http, $route, or other mechanism (e.g. to pre-fill the Edit Profile form with details from the logged in user's account via a GET to /api/v1/users/profile)
If/while the client receives a 401 from the API, show a modal to
login, and replay the API call.
The API call succeeds (in this case, the user can view a pre-filled Edit Profile form for their account.)
How can you do #3? The answer is $http Response Interceptors.
For purposes of global error handling, authentication or any kind of
synchronous or asynchronous preprocessing of received responses, it is
desirable to be able to intercept responses for http requests before
they are handed over to the application code that initiated these
requests. The response interceptors leverage the promise apis to
fulfil this need for both synchronous and asynchronous preprocessing.
http://docs.angularjs.org/api/ng.$http
Now that we know what the ideal user experience should be, how do we do it?
There is an example here: http://witoldsz.github.com/angular-http-auth/
The example is based on this article:
http://www.espeo.pl/2012/02/26/authentication-in-angularjs-application
Good luck and happy Angularing!

App deauthorization: Is there any triggered event by which I can update fbsr cookie without reloading page?

My first post here ! :)
Situation:
User authorized the app and while using it, in the next tab he is removing app from settings page (app deauthorization).
Why:
I want authorize every function call through existing fbsr cookie where its existence is a proof of user login status.
Other solutions:
I can do it using signed request passed in every Canvas POST but I don't want to mix it :)
Before every each call I can refresh login status by FB.getLoginStatus() method
... check every user_id from sr with database entries (what anyway must be done), it's ok but not straight ;)
Just check me/permissions every time you want to verify your user...
FB.api('/me/permissions', function(response) {
var ra = response['data'][0];
pPublishStream = (ra['publish_stream'] == 1);
pCreateEvent = (ra['create_event'] == 1);
if (pPublishStream && pCreateEvent) {
// yay!!!
}
});
Edit: In retrospect, my answer above solves the issues you mentioned but also catches the case where the user removes individual permissions for the app. So maybe it's not exactly what you wanted.