JSF commandlink incorrect navigation - servlets

Before asking this questions I have carefully assessed the feasibility to solve the following problem.
I have an external link being fired from an email viewRequest.xhtml?requestID=6. I use a filter to intercept the incoming request and in case the user is not authenticated it is forwarded to the login.xhtml page. After the user is authenticated the request is forwarded by FacesContext.getCurrentInstane().getExternalContext().redirect(redirected-url) Then it displays the page successfully.
Now if try to logout from same page i.e, viewRequest.xhtml page, the requested URI is viewRequest.xhtml again which takes me to the same page instead of logging out and redirect me to the login page.
I have the real concern of why the request.getRequestedURI in filter is still viewRequest.xhtml instead of login.xhtml
Code for reference
AuthenticationFilter - User is un-authenticated - Adding requested email link in session
String from = req.getRequestURI();
if (req.getQueryString() != null) from += "?" + req.getQueryString();
req.getSession().setAttribute("from", from);
res.sendRedirect(req.getContextPath() + "/faces/pages/login.xhtml");
After user is logged in
if (from != null && !from.isEmpty()) {
externalContext.getSessionMap().remove("from");
externalContext.redirect(from); *-----------Original URL re-direction---------*
return null;
}
else{
result = "adminHome";
}
Now we are in viewRequest.xhtml page - loaded successfully - Now clicked on Log out
String from = req.getRequestURI(); <!--FILTER-->
The value of requestedURI is still viewRequest.xhtml
logout() in LoginController.java
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return login;
Please help. Thank you very much.

Related

Getting an "Unauthorized" error in Dropnet

I'm using Asp.net MVC 4 and Dropnet to download a file from my DropBox account. I'm not sure what is wrong with my code but I get a error whenever I run my project,
Received Response [Unauthorized] : Expected to see [OK]. The HTTP response was [{"error": "Request token has not been properly authorized by a user."}].
Here are my codes,
public ActionResult DropDls()
{
var _client = new DropNetClient("API KEY", "API SECRET");
DropNet.Models.UserLogin login = _client.GetToken();
_client.UserLogin = login;
var url = _client.BuildAuthorizeUrl();
var accessToken = _client.GetAccessToken();
var fileBytes = _client.GetFile("/Getting Started.pdf");
return View();
}
I want only my Dropbox account to be accessed so I need to know how can I give my own USER TOKEN and USER SECRET. I've searched on the web for a solution but couldn't find anything that'll help me.
The problem is you are not getting the user to login before trying to access their dropbox account.
This line should not be there _client.UserLogin = login;
and after this line var url = _client.BuildAuthorizeUrl(); you will need to redirect the user to that url so they can login, then the dropbox site will redirect them back to your site which is when you make the call _client.GetAccessToken(); then you will have access to the users dropbox account.

Cookie not getting created when redirecting?

I have the following in my controller:
public ActionResult Login(string email, string password)
{
/*
some stuff
...
*/
HttpCookie CustomerCookie = new HttpCookie("Customer");
CustomerCookie.Values.Add("FirstName", Customer.FirstName);
CustomerCookie.Values.Add("LastName", Customer.LastName);
CustomerCookie.Values.Add("Email", email);
CustomerCookie.Secure = true;
Response.Cookies.Add(CustomerCookie);
return RedirectToAction("OrderType", "Order");
}
But for some reason when I look for the cookie it is nowhere to be found after the redirect. Based on this question I was assuming that the method above would work.
Can anyone see why my cookie is not being created here?
Some troubleshooting steps I would take:
Remove the redirect and just return an empty view and see if the cookie is there
Do not set Secure to true and see if that's the issue
Force a response flush to see if there's an action filter or something post action execution that's preventing the cookie from being returned in the response
Use fiddler to look at the actual http response for the cookie in case your browser is preventing cookies

Meteor.js google account : filter email and force account choser

In my Meteor.js application, I'm using the accounts-google package in order to be connected with a google account. I have two questions about it.
First, is there a simple way to filter the account used? I would like that the users can connect only with google accounts belonging to my company. Our google account mails end with #mycompany.com. So it would be a simple mail filtering.
I already done that with some post log in hooks but I was wondering if there was a simpler way for doing it.
My second question is how to force the opening of the google account choser. For now, if I try to connect with a wrong google account, and if I only added this account (like in gmail, drive, etc), the google choser doesn't pop and automatically connect with this wrong account. So, in this case, the user is totally blocked (my application disconnect him if he tries to log in with a wrong account but the google account module doesn't propose him to connect with another account).
Thank you for your help.
In order to restrict signup/login to your domain, simply do on the server:
var checkEmailAgainstAllowed = function(email) {
var allowedDomains = ['mycompanydomain.com'];
var allowedEmails = ['otheruser#fromotherdomain.com','anotheruser#fromanotherdomain.com'];
var domain = email.replace(/.*#/,'').toLowerCase();
email = email.toLowerCase();
return _.contains(allowedEmails, email) || _.contains(allowedDomains, domain);
};
Accounts.config({
restrictCreationByEmailDomain: function(email) {
if (!email) {
throw new Meteor.Error(403,'This email address is not allowed');
}
if (!checkEmailAgainstAllowed(email)) {
throw new Meteor.Error(403,'This email domain is not allowed');
}
return true;
}
});
And to login, you'll need on the client:
Meteor.loginWithGoogle({
forceApprovalPrompt: true, //this is what you want, to rerequest approval each time that prompts the google login prompt
loginStyle : "redirect", //or not, depending on your need
requestPermissions : ['profile', 'email'],
requestOfflineToken: true
}, function (err) {
if (err)
// set a session variable to display later if there is a login error
Session.set('loginError', 'reason: ' + err.reason + ' message: ' + err.message || 'Unknown error');
});
Side note:
Alternatively, you can set up your routes so that every time a new route is called, you login, and every time a route is destroyed or on windows's unload, you call logout. This causes login/logout roundtrip everytime the route changes, but you'll make sure that the new user always has a fresh session
Edit:
When you log out of your meteor app, you don't log out of google. That's how oauth works. So, basically, if you want a meteor log out to also log the user out of their google account, so that the next time they come back, they need to provide credentials again, you should do:
Meteor.logout(function(e) {
if (e) {
console.log("Could not log the user out")
} else {
window.location.replace('https://accounts.google.com/Logout');
}
});
This uses the callback of Meteor.logout() so that when the logout is successfull, the user is redirected to google's central account logout url where the user is also logged out of all google services.

WIF, ADFS 2.0, wsignoutcleanup1.0 and wreply

I have set up a WIF web application, a custom STS and an ADFS 2.0 instance as the go between. I am having a hard time understanding the sign out process for my application. Currently, when my user clicks the sign out button, I am calling this code:
WSFederationAuthenticationModule.FederatedSignOut(null, new Uri("https://myrelyingpartyapp.com/?wa=wsignoutcleanup1.0"));
If I use this code, it works fine. All of the cookies and sessions are disposed of correctly. The only problem is that the browser just displays a little green check after the process is over. Obviously, I want to be redirected back to the login page of the STS. To accomplish this I attempted the following code:
WSFederationAuthenticationModule.FederatedSignOut(null, new Uri("https://myrelyingpartyapp.com/?wa=wsignoutcleanup1.0&wreply=" + HttpUtility.UrlEncode("https://myrelyingpartyapp.com/Default.aspx")));
My belief was that the wreply would cause the user to be redirected back to my relying party app where they would be unauthorized and therefore be redirected back to the STS login page. Instead this causes an error in ADFS (which I cannot see because of their helpful error page.) No matter what url I use for wreply, the error is thrown. Am I using wsignoutcleanup1.0 correctly? Just for reference, here is the code in my STS where I handle sign in/sign out requests:
if (action == "wsignin1.0")
{
SignInRequestMessage signInRequestMessage = (SignInRequestMessage)WSFederationMessage.CreateFromUri(Request.Url);
if (User != null && User.Identity != null && User.Identity.IsAuthenticated)
{
SecurityTokenService securityTokenService = new CustomSecurityTokenService(CustomSecurityTokenServiceConfiguration.Current);
SignInResponseMessage signInResponseMessage = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(signInRequestMessage, User as ClaimsPrincipal, securityTokenService);
FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse(signInResponseMessage, Response);
}
else
{
throw new UnauthorizedAccessException();
}
}
else if (action == "wsignout1.0")
{
SignOutRequestMessage signOutRequestMessage = (SignOutRequestMessage)WSFederationMessage.CreateFromUri(Request.Url);
FederatedPassiveSecurityTokenServiceOperations.ProcessSignOutRequest(signOutRequestMessage, User as ClaimsPrincipal, signOutRequestMessage.Reply, Response);
}
All I needed for correct behavior was correct logout code. This code eventually logged my user out and did a proper cleanup:
var module = FederatedAuthentication.WSFederationAuthenticationModule;
module.SignOut(false);
var request = new SignOutRequestMessage(new Uri(module.Issuer), module.Realm);
Response.Redirect(request.WriteQueryString());
This code was put in the event handler of my logout button on my relying party app.

ASP.NET: After returning RedirectResult, URL does not update in browser when https is in use

I'm confused about the behavior of RedirectResult - in some cases (with https), the redirect doesn't seem to happen, but something more like a transfer.
If a user tries to access an internal page without being logged in, they are directed to the login page. After logging in, they're directed back to my app, with query string parameter
schema://host:port/myApp?returnUrl=Inspections.mvc/Edit/43523
The code in the HomeController that handles this looks for the redirectUrl, and does this:
if (returnUrl != null)
{
return Redirect(returnUrl);
}
In my dev environment and one QA environment, I see that a redirect response goes back to the browser, which makes another request, as expected.
But in production and another QA environment (both of which use https), the last redirect doesn't happen. The browser continues to show the url
schema://host:port/myApp?returnUrl=Inspections.mvc/Edit/43523
and displays the content that would be returned by the page Inspections.mvc/Edit/43523.
I'm perplexed - is this expected behavior when RedirectResult is used? Is https the relevant difference?
EDIT: Checking traffic, I see that in the environments using https there IS a redirect (301- moved permanently), but it is back to exactly the same address:
schema://host:port/myApp?returnUrl=Inspections.mvc/Edit/43523
This additional information leaves the mystery as puzzling as ever.
Looking at the source code of RedirectResult class you can see that it should do either a 302 or 301 depending on the kind of redirect you want:
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (context.IsChildAction)
{
throw new InvalidOperationException(MvcResources.RedirectAction_CannotRedirectInChildAction);
}
string destinationUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext);
context.Controller.TempData.Keep();
if (Permanent)
{
context.HttpContext.Response.RedirectPermanent(destinationUrl, endResponse: false);
}
else
{
context.HttpContext.Response.Redirect(destinationUrl, endResponse: false);
}
}
It should be working as expected no matter what schema you are using. Did you look at the actual request/response with a http sniffer such as Fiddler?
Maybe your browser is choosing not to update the URL for some reason and the problem is not in the actual redirect/rewrite.

Resources