HttpClient and WebClient requests / responses don't work for intranet with DefaultCredentials - .net-core

Problem: I am unable to get content from an company internal webpage through using HttpClient or WebClient. I am able to get the content by accessing the URL directly, however.
Details: .NET Core 3.1 Razor Pages, IIS 10, Windows Authentication.
I have a website http://myintranet/Editor/Bib/4343 where a user can press a button to generate a static page. Behind the scenes, it attempts to read a stream from http://myintranet/Editor/NewBib/4343/true and create a static HTML page from it.
When clicking the button, the response is always IIS 10.0 Detailed Error - 401.1 - Unauthorized etc.
However when I access the webpage directly in the browser, it opens up just fine (note that if it is the first time accessing the website, I am prompted by the browser to enter my username and password. After that, the browser remembers these credentials).
Also note that when running it from localhost through Visual Studio, all works fine, the static page downloads properly too.
Here is my code:
Version 1:
public IActionResult OnPostGenerateStaticPage()
{
try
{
HttpClient client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true, PreAuthenticate = true });
HttpResponseMessage response = client.GetAsync(Url.PageLink().Replace("Bib", "NewBib") + "/true").Result;
var indexPageContents = response.Content.ReadAsStreamAsync().Result;
var cd = new System.Net.Mime.ContentDisposition
{
FileName = BibNumber + ".htm",
Inline = false,
};
Response.Headers.Add("Content-Disposition", cd.ToString());
return File(indexPageContents, "text/html");
}
catch (IOException)
{
return RedirectToPage("./Bib");
}
}
Version 2:
public IActionResult OnPostGenerateStaticPage()
{
try
{
WebClient client = new WebClient { UseDefaultCredentials = true };
string desiredUrl = Url.PageLink().Replace("Bib", "NewBib") + "/true";
var indexPageContents = client.OpenRead("desiredUrl");
var cd = new System.Net.Mime.ContentDisposition
{
FileName = BibNumber + ".htm",
Inline = false,
};
Response.Headers.Add("Content-Disposition", cd.ToString());
return File(indexPageContents, "text/html");
}
catch (IOException)
{
return RedirectToPage("./Bib");
}
}
Another thing, I have asked the web server admin to check that NTLM is above Negotiate for the authentication providers for this website and it is. Also, Anonymous and Basic Authentication are disabled and Windows Authentication is enabled.
Not sure where to go from here...

Related

Microsoft sign in works without redirect url

When I sign in with Microsoft OAuth in my Blazor app, authenticateResult.Succeeded is true, even if I don't specify a redirect URI. It's failing as intended for Google, if I don't add my URI to the OAuth client.
Imo it shouldn't work without that redirect URI, according to the OAuth2.0 spec:
The authorization server MUST require public clients and SHOULD
require confidential clients to register their redirection URIs.
I'm using Microsoft.AspNetCore.Authentication.MicrosoftAccount 3.0.3 with .NET Core 3.0
public class ExternalLoginModel : PageModel
{
public IActionResult OnGetAsync(string externalAuthType, string returnUrl)
{
var authenticationProperties = new AuthenticationProperties
{
RedirectUri = Url.Page("./externallogin",
pageHandler: "Callback",
values: new { returnUrl }),
};
return new ChallengeResult(externalAuthType, authenticationProperties);
}
public async Task<IActionResult> OnGetCallbackAsync(
string returnUrl = null, string remoteError = null)
{
var authenticateResult = await HttpContext.AuthenticateAsync("External");
if (!authenticateResult.Succeeded) // Should be false for Microsoft sign in
return BadRequest();
...
return LocalRedirect(returnUrl);
}
}
With the following added to my Startup:
services.AddAuthentication(o =>
{
o.DefaultSignInScheme = "External";
}).AddCookie("External");
services.AddAuthentication().AddGoogle(google =>
{
google.ClientId = Configuration["Authentication:Google:ClientId"];
google.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
});
services.AddAuthentication().AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.ClientId = Configuration["Authentication:Microsoft:ClientId"];
microsoftOptions.ClientSecret = Configuration["Authentication:Microsoft:ClientSecret"];
});
My App's Authentication settings look like this (I'm actually using localhost:12345 in the settings, but that's not what my app is running on..):
Ironically the last sentence might explain it, but I don't even know which flow the MicrosoftAccount library is using and I only get generic documentation when googling.
It fails as intended when using a completely different domain, not localhost with different ports. I guess that's good enough.
Additionally I unchecked "ID token" and "Treat application as a public client", therefore Authorization code flow should be used, to my understanding.

Internal Server Error when I send my own certificate to Azure Cloud Service

I'm trying to access the Azure Elastic Scale Split/Merge tool from an ASP.NET application. I can open the page in my browser after I use the certificate that I uploaded on Azure. But when I try to connect to the page in ASP.NET I keep getting 500 Internal Server Error, even though I used the certificate in my request.
Is there something wrong with the code below? Have I been forgetting something?
var handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = delegate { return true; };
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(Cert); //Cert is the X509Certificate2 I use
using (var client = new HttpClient(handler))
{
try
{
var response = await client.GetAsync(Endpoint); //Endpoint = https://foobar.cloudapp.net/
if (response.IsSuccessStatusCode)
{
var a = response.Content.ReadAsStringAsync();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
Found where I went wrong. When creating the Certificate I was using the .cer file, but it works now with the .pfx file

redirect_uri_mismatch in Google APIs in ASP.NET

I am trying to upload video on my YouTube channel using ASP.NET Web Form. I created developer account and tested it working using JavaScript based solution which requires login every-time to upload a video.
I want users of my website to upload video directly on my channel and every auth should be in code behind, user should not be prompted to login. For this I wrote following class:
public class UploadVideo
{
public async Task Run(string filePath)
{
string CLIENT_ID = "1111111111111111111111.apps.googleusercontent.com";
string CLIENT_SECRET = "234JEjkwkdfh1111";
var youtubeService = AuthenticateOauth(CLIENT_ID, CLIENT_SECRET, "SingleUser");
var video = new Video();
video.Snippet = new VideoSnippet();
video.Snippet.Title = "Default Video Title";
video.Snippet.Description = "Default Video Description";
video.Snippet.Tags = new string[] { "tag1", "tag2" };
video.Snippet.CategoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
video.Status = new VideoStatus();
video.Status.PrivacyStatus = "unlisted"; // or "private" or "public"
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;
await videosInsertRequest.UploadAsync();
}
}
void videosInsertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress progress)
{
switch (progress.Status)
{
case UploadStatus.Uploading:
//Console.WriteLine("{0} bytes sent.", progress.BytesSent);
break;
case UploadStatus.Failed:
//Console.WriteLine("An error prevented the upload from completing.\n{0}", progress.Exception);
break;
}
}
void videosInsertRequest_ResponseReceived(Video video)
{
Console.WriteLine("Video id '{0}' was successfully uploaded.", video.Id);
}
public static YouTubeService AuthenticateOauth(string clientId, string clientSecret, string userName)
{
string[] scopes = new string[] { YouTubeService.Scope.Youtube, // view and manage your YouTube account
YouTubeService.Scope.YoutubeForceSsl,
YouTubeService.Scope.Youtubepartner,
YouTubeService.Scope.YoutubepartnerChannelAudit,
YouTubeService.Scope.YoutubeReadonly,
YouTubeService.Scope.YoutubeUpload};
try
{
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, userName
, CancellationToken.None
, new FileDataStore("Daimto.YouTube.Auth.Store")).Result;
YouTubeService service = new YouTubeService(new YouTubeService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "YouTube Data API Sample",
});
return service;
}
catch (Exception ex)
{
//Console.WriteLine(ex.InnerException);
return null;
}
}
}
Now using this class into Page_Load() of default.aspx, as given below:
protected void Page_Load(object sender, EventArgs e)
{
try
{
string path = "C:/Users/abhi/Desktop/TestClip.mp4";
new UploadVideo().Run(path).Wait();
}
catch (AggregateException ex)
{
//catch exceptions
}
}
When I run this (default.aspx) page, i see http://localhost:29540/default.aspx spins, so I used them on Google Developer Console as given below:
Upon running http://localhost:29540/default.aspx opens a new tab which displays "redirect_uri_mismatch" error as given below:
At this point if I look in browser address, I see redirect_uri is set to http://localhost:37294/authorize and I just manually change this to http://localhost:29540/default.aspx which generates a token.
So, can you suggest where to make changes in above code so that request uri fills up correctly from my app side.
A day waste then I came to know below redirect URL is working for all localhost web applications. So you need to use below URL on google developer console web application's "Authorized redirect URIs".
http://localhost/authorize/
For anybody still having this issue in 2022, I figured out a solution. If you are using https://localhost:portnumb as your redirect uri, just use https://127.0.0.1:sameportnumb as your redirect uri. It ended up working for me

CRM 2011 Online via an ASP.net application does not work, same code via Console Application Works -> "Authentication Failure"-error

I'm trying to connect to a CRM 2011 Online environment. I'm able to connect via a "Console Application", but when I'm trying to connect via an "ASP.net"-application with the same code, it doesn't work, it gives me the "Authentication Failure"-error ({"An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail."}).
Is there something special we need to do to make it work on an "ASP.net" environment. I tested out several solutions I found on the internet, but all gives me the same error.
A "code"-snippet of my simplified code:
private static ClientCredentials GetDeviceCredentials()
{
return Microsoft.Crm.Services.Utility.DeviceIdManager.LoadOrRegisterDevice();
}
protected void Button1_Click(object sender, EventArgs e)
{
//Authenticate using credentials of the logged in user;
string UserName = "*****"; //your Windows Live ID
string Password = "*****"; // your password
ClientCredentials Credentials = new ClientCredentials();
Credentials.UserName.UserName = UserName;
Credentials.UserName.Password = Password;
Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
//This URL needs to be updated to match the servername and Organization for the environment.
Uri OrganizationUri = new Uri("https://*****.crm4.dynamics.com/XRMServices/2011/Organization.svc"); //this URL could copy from Setting --> Developer Source
Uri HomeRealmUri = null;
//OrganizationServiceProxy serviceProxy;
using (OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, Credentials, GetDeviceCredentials()))
{
IOrganizationService service = (IOrganizationService)serviceProxy;
OrganizationServiceContext orgContext = new OrganizationServiceContext(service);
var theAccounts = orgContext.CreateQuery<Account>().Take(1).ToList();
Response.Write(theAccounts.First().Name);
}
}
I tried several things, like deleting the content of "LiveDeviceID"-folder an re-running the device registration tool. but is weird that it works in the "console application" but not on my "asp.net"-solution...
PS : I am able to generate the "context"-file via crmsvcutil.exe /url:https://org.crm4.dynamics.com/XRMServices/2011/Organization.svc /o:crm.cs /u:username /p:password /di:deviceUserName /dp:devicPWD
Is there any particular reason you have
Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
You shouldn't need that line for windows live authentication.
Even with that the code seems valid so it is something to do with the Device Registration. I suggest rather than just call it directly like you have
using (OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, Credentials, GetDeviceCredentials()))
{
You try something like the following because you only need to register once:
ClientCredentials deviceCredentials;
if ((CRMSettings.Default.DeviceID == String.Empty) || (CRMSettings.Default.DevicePassword == String.Empty))
{
deviceCredentials = Microsoft.Crm.Services.Utility.DeviceIdManager.RegisterDevice();
}
else
{
deviceCredentials = new ClientCredentials();
deviceCredentials.UserName.UserName = CRMSettings.Default.DeviceID;
deviceCredentials.UserName.Password = CRMSettings.Default.DevicePassword;
}
using (OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(OrganizationUri, HomeRealmUri, Credentials, deviceCredentials))
{
I have had issues in the past where I get an "already registered" response from the RegisterDevice call.
I would also dump out the Device ID and Password so you can see if they are being set.

ASP.NET Forms Authentication Cookie not set in Safari

I have a ASP.NET Web Service which exposes a method called DoLogin
[WebService(Namespace = "http://rtns.ism.ec/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class UserManagerService : WebServiceBase
{
[WebMethod(EnableSession=true)]
[ScriptMethod]
public ResponseBase<bool> DoLogin(LoginCredentials Credentials)
{
Credentials.IpAddress = HttpContext.Current.Request.UserHostAddress;
Credentials.ServerID = Environment.MachineName;
Credentials.SystemID = WebConfigurationManager.AppSettings["SYSTEM_ID"];
Credentials.UserAgent = HttpContext.Current.Request.UserAgent;
try
{
DataResponse<User> resp = UserManager.LoginUser(Credentials);
if (resp.Code)
{
FormsAuthentication.SetAuthCookie(Credentials.Email, true);
HttpContext.Current.Session.Add(Constants.Identifiers.USER_SESSION_INFO_IDENTIFIER, resp.Data);
}
return resp;
}
catch (Exception _ex)
{
ISM.Essentials.Business.LogManager.SaveLog(_ex);
return new ResponseBase<bool> { Message = MessageManager.Instance[Constants.Messages.E_GENERIC_FAILURE, Credentials.CultureID] };
}
}
}
I have a JQuery client, which makes the call:
function loginSubmitHandler() {
var objeto = {
Email: $('#txtUser').val(),
Password: $('#txtPassword').val(),
CultureID: $('#hddCulture').val()
};
utils.startAjaxCall('../Services/UserManagerService.asmx/DoLogin', { Credentials: objeto }, function(data) {
if (data.d.Code) {
window.location.replace('home.aspx');
}
else
{
utils.alert(locals.Information, locals.Accept, data.d.Message);
}
});
return false;
}
When I log in with icorrect credentials, the alert with the message sent from the server appears. If I give correct credentials, the page is redirected to home.aspx
This code is working 100% fine since the begining in the following browsers:
IE6, 7, 8, 9
Mozilla
IE9 Windows Phone
Android 2.3 Browser
Safari 5.1 for Windows
I've just got a Mac (first ever) and when I tried to access my website, I noticed an extrange behavior. I give correct login credentials, I'm redirected to home, but the FormsAuthentication mechanism redirects back to the login page.
It seems like the Auth cookie returned back from the server is just ignored.
This is not an issue with cross domain cookies, as I'm calling the web server in the same web application/domain.
Any ideas on how to make Safari for Mac to accept the cookies returned in an Ajax Web Service call?
The problem might be that safari will not set cookies with non-ASCII characters. Try using encodeURIComponent() function on cookie values. Here is a link with similar problem:
Strange problem with cookies in Safari and Asp.net

Resources