Incomplete URL returned from application - asp.net

I am creating an application in VS2013, using VB and webforms. I came to discover that the support for webforms is quite reduced, everybody seems to be going the MVC way. Anyway the issue I am having is request URL misses out the application name in the URL. As an example what what my problem is on my development machine it returns the complete URL but, on the test server where I created it as an application on IIS it misses out the application name, this make the link incomplete.
It returns
http://tsv/Account/Forgot.aspx
instead of
http://tsv/itstock/Account/Forgot.aspx
tsv is the name for my local test server
How can i make it include itstock to make my URL complete
The code that gives the error is found in the IdentityModels.vb
Public Shared Function GetResetPasswordRedirectUrl(code As String, request As HttpRequest) As String
Dim absoluteUri = "/Account/ResetPassword?" + CodeKey + "=" + HttpUtility.UrlEncode(code)
Return New Uri(request.Url, absoluteUri).AbsoluteUri.ToString()
End Function
NB: I am using ASPNET Identity.

Have you thought about prefixing the string? or is this a dynamic url? Try the below:
Public Shared Function GetResetPasswordRedirectUrl(code As String, request As HttpRequest) As String
Dim absoluteUri = "/itstock/Account/ResetPassword?" + CodeKey + "=" + HttpUtility.UrlEncode(code)
Return New Uri(request.Url, absoluteUri).AbsoluteUri.ToString()
End Function

Related

Why app is throwing error in test environment but working fine in local machine using ASP.NET Web Forms and MSAL?

Scenario:
Using the application, customer can access the emails in within the application and decide to save it. I have used Exchange Web Service Managed API for this. Things were working fine until IT implemented Multi factor Authentication. Now the program cannot access the mailbox based on the username and password.
Solution
In order to overcome this issue I integrated MSAL(Microsoft Authentication Library) to acquire the Access token in order to use it with the EWS Managed API to access the emails. I have registered an application in the Azure and used the clientID and TenentID. It works perfectly fine when testing locally. But throws an error when deploying in dev/test environnment. I am not sure what to do. Could you please help me with this?
Private Function GetDelegatedExService() As ExchangeService
If Session("EwsOAuthToken") Is Nothing Then
Dim caller As New AsyncGetToken(AddressOf GetDelegatedToken)
' Initiate the asynchronous call.
Dim result As IAsyncResult = caller.BeginInvoke(Nothing, Nothing)
' thread from any process ready to run and has a higher priority then Sleep(0) will yield the processor and let it run
Thread.Sleep(0)
' Perform additional processing here and then wait for the WaitHandle to be signaled.
result.AsyncWaitHandle.WaitOne()
' Call EndInvoke to retrieve the results.
Dim returnValue As String = caller.EndInvoke(result)
Session("EwsOAuthToken") = returnValue
End If
Dim ewsClient = New ExchangeService()
ewsClient.Url = New Uri("https://outlook.office365.com/EWS/Exchange.asmx")
Dim myToken = Session("EwsOAuthToken").ToString()
' Setup OAuthCredentials with the token
ewsClient.Credentials = New OAuthCredentials(myToken)
Return ewsClient
End Function
Private Function GetDelegatedToken() As String
Dim pcaOptions = New PublicClientApplicationOptions() With
{
.ClientId = ConfigurationManager.AppSettings("appId"),
.TenantId = ConfigurationManager.AppSettings("tenantId")
}
Dim redirectUrl = ConfigurationManager.AppSettings("EBWebURL")
Dim pca = PublicClientApplicationBuilder _
.CreateWithApplicationOptions(pcaOptions) _
.WithRedirectUri(redirectUrl) _
.Build()
' The permission scope required for EWS access
Dim token = OpenAuthPopup(pca).GetAwaiter().GetResult()
Return token
End Function
Private Async Function OpenAuthPopup(pca As PublicClientApplication) As Tasks.Task(Of String)
Dim ewsScopes = {"https://outlook.office365.com/EWS.AccessAsUser.All"}
Dim authResult = Await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync()
Return authResult.AccessToken
End Function
This is the local testing where user is able to get the login by Microsoft account prompt. They have to enter their organization account details, gets the Multi Factor Auth code in phone, adds in the prompt and then gets authenticated(it simply returns a access token).
But when the code is deployed to DEV/TEST environment. I get the following error. It is not even prompting for the Microsoft Login. And I tried searching for the given error, but not able to figure out what the problem actually is with the asp.net web app or Microsoft Auth Library.
I am not experienced with the technologies you describe in your question but I will try to give you my persepctive on the issue. From what I can understand, the code you have pasted here is supposed to run on the web-server. Testing the application locally, the client is requesting information from the web-server but the web-server needs first to aqcuire an authentication token. The modal window that appears on the screen, asking from the client to authenticate, seems to be fired by
pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync()
This code runs on the web-server and it is the web-server that shows this pop-up. The clients can only enter their credentials because the testing is taking place on the same machine where the web-server lives. In produciton environments, web app code is not allowed to open a modal window. Even if it was permitted, there would be no one there to interact with the pop-up.
I checked the MSIL library and I found that PublicClientApplication contains more authentication methods and some of them are non-interactive, such as AquireTokenByUsernamePassword. I am not sure how you can handle the code received by the user's mobile. I cannot help any further on the library since I am not familiar with it.
Another option might be to make the client-browser open a pop-up window on https://outlook.office365.com/EWS.AccessAsUser.All and somehow return the authorization token back to the web-server. You might want to take a look at this and see if it suits your needs.

WSFederationAuthenticationModule: RedirectToIdentityProvider: Does the realm have to be a subset of the request URL?

Like so many others dealing with WIF in .NET I ran into the usual error:
ID3206: A SignInResponse message may only redirect within the current
web application.
I wrote a custom authentication module where I overrode RedirectToIdentityProvider as suggested in Error - A SignInResponse message may only redirect within the current web application - MVC 2.0 application.
The suggested code sample did not take into account that the request URL might include parameters, i.e. it would simply append a trailing slash to the full URL. Eventually I expanded that code to what you see below but still used the realm in order to decide whether or not to process the URL:
Public Overrides Sub RedirectToIdentityProvider(ByVal uniqueId As String, ByVal returnUrl As String, ByVal persist As Boolean)
Dim absoluteUri As String = HttpContext.Current.Request.Url.AbsoluteUri
Dim ciAbsoluteUri As String = absoluteUri.ToLowerInvariant
Dim realm As String = MyBase.Realm
Dim ciRealm As String = realm.ToLowerInvariant
'If Realm ends with a trailing slash, the returnUrl should include a trailing slash in the same position.
'This trailing slash may or may not be the end of the returnUrl, depending on whether or not additional parameters have been provided.
If realm.EndsWith("/") Then
If Not ciAbsoluteUri.StartsWith(ciRealm) Then
Dim realmWithoutSlash As String = realm.Substring(0, realm.Length - 1)
Dim ciRealmWithoutSlash As String = realmWithoutSlash.ToLowerInvariant
If ciAbsoluteUri.StartsWith(ciRealmWithoutSlash) Then
'Realm ends with a slash and AbsoluteUri contains Realm but without a slash.
Dim absolutePath As String = HttpContext.Current.Request.Url.AbsolutePath
returnUrl = returnUrl.Replace(absolutePath, absolutePath & "/")
End If
End If
End If
MyBase.RedirectToIdentityProvider(uniqueId, returnUrl, persist)
End Sub
(This could have been written more compactly but that is besides the point.)
The code in the original post includes the following comment
//Compare if Request Url +"/" is equal to the Realm, so only root access is corrected
//https://localhost/AppName plus "/" is equal to https://localhost/AppName/
//This is to avoid MVC urls
It is perfectly possible to set the realm and audienceUri in the web.config file and the identifier on the AD FS 2.0 side to something other than a subset of the request URL as long as the value is a valid URI. For example, a bogus value of "http://corp.com" would suffice. However, using such a value would mean that the request URL would not be processed by the RedirectToIdentityProvider override.
My questions are:
What is the reason for having the realm being a subset of the request URL in an MVC application and - more importantly - is there a reason for requiring the same for a non-MVC application?
Could I not just ignore the realm and ensure that the URL includes a slash at the end (in case of no parameters) or before a list of parameters?
Just some basics: Realm is WIF language for EntityID in metadata. It should be a URI. Which means that it doesn't have to be a URL. Almost all implementations are very tolerant and do accept any string in EntityID.
Returnurl in this case means the url where the browser will go after the user has been authenticated and WIF has set the session cookie. It should be within the app (why else authenticate). If you really do want the application root then the ending slash is a good idea indeed (because of cookiepath). So the usage of Realm (in this particular case) is a mistake.

I need to create replica of asp.net in classic asp code. Please suggest

I need classic asp code of following asp.net code.
asp.net-System.Environment.MachineName
asp.net-Server.MapPath
ASP Server.MapPath doesn't support the resolution of "~/" at the start of URL as ASP.NET version does. Here is code I posted here last year:
Function UrlContent(sUrl)
If InStr(1, sUrl, "~/") = 1 Then
UrlContent = ApplicationPath & Mid(sUrl, 2)
Else
UrlContent = sUrl
End If
End Function
Function ApplicationPath()
Dim pos: pos = Len(Request.ServerVariables("INSTANCE_META_PATH")) + 6
ApplicationPath = Mid(Request.ServerVariables("APPL_MD_PATH"), pos)
End Function
The UriContent takes the passed in URL and resolves an "~/" to return a url relative to the host website. So an MapPath equivalent to ASP.NETs code is:
Dim physicalPath : physicalPath = Server.MapPath(UrlContent(virtualPath))
Getting the machine name is much harder since you need some access to the windows API. The server variable called "SERVER_NAME" is simply the host name used in the request so its not the same as the actually windows machine name.
Its moderately easy to create a .NET COM Interop dll that will allow script to access the Environment.

Get domain whatever local or webserver

I wrote an ASP.NET web application. My application created a request with returning URL other e-commerce server. I want to get this.
http://www.stackoverflow.com/question/ask --> http://www.stackoverflow.com
http://localhost/stackoverflow/question/ask --> http://localhost/stackoverflow
I used Request.Url.AbsoluteUri. But it's not OK for typing address by user.
How can this be done?
Look at the server variables collection. That is the source of this raw data that the HttpApplication gets from IIS.
I think the specific string you are looking for can be found with by "http://" + HttpContext.Current.Request.ServerVariables["SERVER_NAME"]
EDIT
Looking at your question again, this won't work for the "http://localhost/stackoverflow". This is because it doesn't follow the same convention. If you are using the convention that the public site is http://www.domainname.com/ and your development site is http://localhost/domainname, then you could write a function that gets the site name like
public static string GetDomainUrl(){
var servername = HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
bool isLocalHost = serverName.ToLowerInvariant().Contains("localhost);
if(isLocalHost){
var domain = serverName.Split(new Char[]{'/'})[1];
return string.Format(#"http://localhost/{0}", domain);
}
return string.Format(#"http://{0}", serverName);
}
Note: I wrote this in the SO textbox, so check it.

Get application root from Request object that works locally and remotely

Let's say that I have my ASP.NET web application in a directory called "MyApp" both locally and on a remote server. I'm trying to build an onclick response to a link. The response calls a Javascript function, passing it the URL of an .aspx page in my web app. The Javascript pops out a new window displaying the page. My C# code looks like this:
link = new HyperLink();
link.Text = product_num_str;
link.NavigateUrl = "#";
string url = "Javascript:My_NewWindow('http://" +
HttpContext.Current.Request.Url.Authority +
"/ProductInfo.aspx?_num=" + product_num_str + "')";
link.Attributes.Add("onclick", url);
I started using the Request's Authority property because I was having problems running locally on the Visual Studio web server when I used the Host property. The problem was that Host only returned "localhost" instead of the host and port number.
When tested locally, the code works because the "authority" maps to my app root folder. The URL generated is, e.g.,
http://localhost:52071/ProductInfo.aspx?_num=123
If I run on a remote server, however, I end up with something like:
http://company-server/ProductInfo.aspx?_num=123
This fails to find the page, because in this case the "MyApp" root folder must be included.
There is probably an easier way - putting an entry in the web.config or something. My motivation originally was to allow the app to be published to a folder of any name and work as is.
I could hack my approach and search the string for "localhost" or something, but that's ugly. So how do I build a string that will work everywhere?
I'm assuming you're doing this from within a Page or Control. If that's the case you should do this instead:
string fullUrl = this.ResolveClientUrl("~/ProductInfo.aspx?_num=" + product_num_str + ");
That will give you the proper URL no matter where the application is deployed.

Resources