how to redirect the user to page in different app - forms-authentication

i have two web projects authenticating the user using configuration.
let say web1,web2 once the user logs into web1 there a link is provided to web2 .
When a user requests a particular page in web2 app, it is redirected to login page once validated i wants to redirect to requested page.
I'm using
strRedirect = Request.QueryString["ReturnUrl"];
if (strRedirect == null)
{
strRedirect = "~/default.aspx";
Response.Redirect(strRedirect);
}
else
{
Response.Redirect(strRedirect);
}
but this gives only relative path. By using URI url=Request.url gives the full path so how can i redirect the user to this page....?????

I made correction in my web.config then it is working fine

Related

Using OAuth2 in Blazor and redirect user based on claims to certain page after successfull login

I use keycloak (OAuth2/Open ID Connect) to authorize and authenticate users in a Blazor Server Side application. Furthermore I use the services.AddAuthentication().AddOpenIdConnect() extension from Microsoft.
After successfull login I want to redirect the user to a certain page based on its claims. So f.e. if the user has the claim "gis" he should be redirected to "/gis" or if he has the claim "claim123" he should be redirected to page "/page456".
Right now I solve this problem by overriding OnInitialized in the MainLayout.razor and look if the user has a certain claim and then redirect him with the help of the NavigationManager.
#inject NavigationManager navMan;
//...
protected override void OnInitialized()
{
if (_user.HasClaim(t => t.Type == "claim123"))
{
navMan.NavigateTo("/page456");
}
}
The problem with this approach is, that it will first load the default index home page ( "/" ) and then after a short period of time will reload to the new destination. This "flickering" is not very nice and I thought there must be a better way to directly redirect after successful "/openid-connect" redirection. Can I may use some kind of middleware or one of the OpenIdConnectEvents?

Asp.Net Identity Unauthorized redirect Not Working with Custom Routes

Forms Authentication used to redirect to the login page when a folder was configured to restrict authentication to a user. As configured in the web.config, in the folder.
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
Which would redirect you to the login page with the returnurl of where you wanted to go in the first place. The authorization works ( Identity 2.0 Beta1 prerelease ) but there is no redirect to the login page and I'm not able to make this happen though Ive gone through quite a bit on Identity. Now, after implementing identity which does everything else quiet well, when I try to access a page that requires me to be logged in I see a YSOD saying.
An error occurred while accessing the resources required to serve this request. You might not have permission to view the requested resources.
I've used the default template from vs2013 and as soon as I put in the custom route it stopped working and I've tried soo many things, I just can't get it to work..
I figured out that when I enabled FriendlyUrls or the full path of the resource and used the url route to a resource that was restricted to Logged in users it worked.
For example I have a page located at /Account/nightlife/stream.aspx which has that web.config in the folder Account
So when I use the full path it works and sends me to the login page with
http://mylocaliis/login?ReturnUrl=%2FAccount%2Fnightlife%2Fstream.aspx (without the .aspx in the case of friendly urls)
When I was using Forms Authentication a few weeks ago this problem didnt exist with the custom route you can see for the login page
(which is - routes.MapPageRoute( routeName:"login", routeUrl: "login", physicalFile: "~/Account/Login.aspx" ); )
But with Identity and the custom route enabled the redirect dosent happen and I see the YSOD
So for example if i tried to access the resource (when I am not logged in) with its custom route url
localhost/stream (defined by the custom route - routes.MapPageRoute( "nightlife_stream", "stream", "~/Account/nightlife/stream.aspx" ); )
I see the YSOD.
I know this post is old, but I just ran into this today as well and fixed it. Basically, if you create a route and the user is not logged in but needs to be, you get the YSOD (yellow screen of death) even though your MapPageRoute specifies true for the "checkPhysicalUrlAccess" parameter.
To resolve this, I added a check in the Application_AuthenticationRequest method of Global.asax. So, my code is something like this...
Inside Application_Start in Global.asax I registered my route:
RouteTable.Routes.MapPageRoute("EditAPage", "editpage/{pageToken}", "Admin/editpage.aspx", true);
Then I added this to Global.asax:
void Application_AuthenticateRequest(object sender, EventArgs e)
{
var user = HttpContext.Current.User;
string url = Request.Url.ToString();
if (url.Contains("/editpage") && user == null)
{
Response.Redirect("~/Account/Login.aspx?ReturnUrl=%2Feditpage");
}
}
I will need to evolve this a bit more as I also have additional pages where a user needs to be authenticated and authorized and it would be ideal not to have to create an individual check for each route that I end up adding... but, for now, this is redirecting my user's to login. I will also need to add handling to append the {pageToken} to the ReturnUrl - if the token is provided that is.
I am working on a legacy project and had to fix this issue.
Unauthorized access normally has Http Code of 401
The app throws a YSOD meaning the error may have to go through Application_Error in Global.asax and the error may not be necessarily a HttpException
If it is an error of HttpCode 401, then use HttpContext.Current.ClearError() method to clear the current error and prevent YSOD.
Solution:
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
Exception ex = Server.GetLastError();
try
{
HttpException httpException = (HttpException)ex;
int httpCode = httpException.GetHttpCode();
if (httpCode == 401)
{
HttpContext.Current.ClearError();
string url = Request.Url.PathAndQuery;
Response.Redirect($"~/LogIn/?ReturnUrl={url}");
}
else
{
//Log Your Error
}
}
catch
{
//Log Your Error
}
}

Asp.net Allow access to Admin Only

I have a admin page in the secret folder and it should only be accessed by an admin. The way I attempted was creating a session and check if the logged in person is admin. This failed to recognise the admin. Following is what I attempted. Can anyone see where I went wrong? Is it because the admin page is in a different folder and when I created the session it wouldn't recognise it when I access the admin area? If so, how can i overcome this?
if (Session["username"] != "admin")
{
Response.Redirect("~/NotAdmin.aspx");
}
else
{
showtables();
}
Get the username via HttpContext class
var user = HttpContext.Current.User.Identity.Name;
if (user!= "admin")
{
Response.Redirect("~/NotAdmin.aspx");
}
else
{
showtables();
}
In my opinion sessions are not good to work with it. What if your application is hosted on a load balanced server. If the server is being load balanced, your users will lose their session state information when the load balancer sends their request to another server.

Detecting forms authentication timeout in login page

When you have forms authentication setup to redirect to login.aspx when accessing a protected page, what's a good way to detect in login.aspx whether the user was sent there because they haven't logged on yet, or because their forms auth ticket is expired? I'd like to display a "you've timed out" message.
(I do not mention the word session in this question, because ASP.NET treats them so distinctly, however, if there is a good solution that involves session, I'm all ears)
I've solved this in the past by having another cooke "hasloggedin" set when a user logs in and then checks to see if that exists to determine if it's a timeout and then display an appropriate message. But, this has to be a common problem?
Forms authentication will automatically append a URL parameter 'ReturnURL', indicating what page (if any) triggered the redirection to the login page. Most websites have a 'Default.aspx' or 'index.html' etc as the default page. You can check the ReturnURL to see if it contains the default page, or some other page in your application.
EXAMPLE:
string refererURL;
if (page.Request.QueryString["ReturnURL"] != null)
{
refererURL = page.Request.QueryString["ReturnURL"].ToString();
}
//Check to see if user was redirected because of Timeout or initial login
//Where "Default.aspx" is the default page for your application
if (refererURL != "" && refererURL != (ResolveUrl("~") + "Default.aspx"))
{
//Show HTML etc showing session timeout message
}
else // User redirected here to to initial login
{
//Show HTML showing initial login HTML message etc
}

Store cookie for other site

I have multiple asp.net sites. When a user logs unto one of the sites, I want to store a cookie telling me that a user has logged on. When the user later visits one of the other sites I have, I would like to read the cookie from that site.
AFAIK you neither can read cookies from or write cookies to other sites, so what could a workaround be?
Perhaps making a redirect to http://www.othersite.com/SaveCookie.aspx ?
Give me some ideas :-)
One of our clients has exactly the same requirement (logging into multiple sites on different domains), complicated by the fact that one of the sites requires that the user is logged in to a classic ASP application, a .NET 1.1 application and a .NET 3.5 application running on different hardware, but under the same domain...
We've basically implemented a system of round-robin style redirects, where each domain logs the user in, then bounces them on to the next domain until they return to the original domain at which point they are redirected to their original request.
So (pages and domains changed to protect the innocent):
User requests www.example1.com/page1.aspx
A cookie is set that tells us the user was attempting to access page1.aspx, and the user is sent to the www.example1.com/login.aspx
The user logs in, and is then redirected to www.example2.com/processlogin.aspx?token=EncryptedToken
ProcessLogin.aspx checks for a cookie telling it where to direct the user, if it can't find one, it decrypts the token, logs the user in on example2.com, and then redirects them to www.example1.com/processlogin.aspx?token=EncryptedToken (or example3.com - repeat as required)
As in 4, ProcessLogin.aspx checks for the cookie, finds it, deletes it and redirects the user to /page1.aspx.
If the user later on visits a page on www.example2.com, before the authentication ticket timeout, they will still be logged in on that site as well.
Edit to respond to comment
That depends on how you are making the "request to the other pages". If you make the request from your code behind, what you're doing is effectively setting the cookie on the server, rather than on the users browser.
Cookies need to be issued by the server to the client browser, and that is done in the headers of the page response - so you need to direct the users browser to a page on the other site to issue the cookie from that domain.
You could generate a request to the other page in an IFrame, or try and do it in a self closing pop-up window - but that has other issues like pop-up blockers, flickering windows, etc.
After some investigation we found that a round-robin set of redirects like this was the simplest and most reliable solution.
A very basic code setup:
An .aspx page, containing a Login control, with a method "OnLoggedIn" attached to the LoggedIn event of the control:
void OnLoggedIn(object sender, EventArgs e){
string returnUrl = Request.QueryString["returnUrl"];
// Create new cookie, store value, and add to cookie collection
HttpCookie myCookie = new HttpCookie("WhereTo");
myCookie["ReturnUrl"] = ReturnUrl;
Response.Cookies.Add(myCookie);
// Redirect user to roundtrip login processor on next domain.
// Work out domain as required.
string redirect = GetNextDomain();
// Add encoded user token
redirect += "?token=" + EncodeUserToken();
// Redirect the user, and end further processing on this thread
Response.Redirect(redirect, true);
}
Then on both servers you have ProcessLogin.aspx, that has something like this in it:
protected void Page_Load(object sender, EventArgs e){
// Look for redirect cookie
if (Request.Cookies["WhereTo"]["ReturnUrl"] != null){
// Save value from cookie
string redirect = Request.Cookies["WhereTo"]["ReturnUrl"];
// Delete original cookie by creating an empty one, and setting it
// to expire yesterday, and add it to the response.
HttpCookie myCookie = new HttpCookie("WhereTo");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
// Redirect the user, and stop processing
Response.Redirect(redirect, true);
}
// Still here, so log in and redirect
string encryptedToken = Request.QueryString["token"];
if (!string.IsNullOrEmpty(encryptedToken)){
// Decrypt token, and log user in
// This will vary depending on your authentication mechanism
PerformLogin(encryptedToken);
}
// Redirect user to roundtrip login processor on next domain.
// Work out domain as required.
string redirect = GetNextDomain();
// Add encoded user token - no need to recalculate, it will be the same
redirect += "?token=" + encryptedToken;
// Redirect the user, and end further processing on this thread
Response.Redirect(redirect, true);
}
You're looking for a Single Sign-On (SSO) solution.
If it's possible for you to host your sites at different subdomains below the same domain, you can save cookies that are shared for the whole domain, e.g.:
"site1.yourdomain.com" and
"site2.yourdomain.com"
can both read cookies saved to the domain "yourdomain.com"
Another alternative is to tell the other site about the login via a request to it, as in your redirect suggestion. You could do this in several ways, e.g. by loading the page in an iframe, sending the data directly from one server to another, and so on. None of these are particularly elegant, though, and in the case of login, as Tomas Lycken says, you should really be going for a proper SSO implementation.

Resources