Getting Microsoft.VisualStudio.Services.Common.VssUnauthorizedException: 'VS30063 when trying to lauch in local IIS - asp.net-core

im running a simple web application testing out the TeamFoundation.Services.Client along side VisualStudio.Services.Common and launching the app via IIS Express is no problem but when I try to do the same using Local IIS I get this error:
Microsoft.VisualStudio.Services.Common.VssUnauthorizedException: 'VS30063: You are not authorized to access http://mytfs:8080.
This exception was originally thrown at this call stack:
Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
Microsoft.VisualStudio.Services.Common.VssHttpRetryMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage, System.Threading.CancellationToken)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
System.Net.Http.HttpClient.FinishSendAsyncBuffered(System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>, System.Net.Http.HttpRequestMessage, System.Threading.CancellationTokenSource, bool)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
...
[Call Stack Truncated]
I don't understand what the problem is.
This is the debug profile in which im trying to launch it:
This is the code where I get the error:
internal const string vstsCollectioUrl = "http://myTFS:8080/tfs/MyCollection";
//Prompt user for credential
VssConnection connection = new VssConnection(new Uri(vstsCollectioUrl), new VssAadCredential("{user}", "{password}"));
//create http client and query for resutls
WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>();

The VssAadCredential class by default takes the credentials of the person running the tool and does not honor the username and password parameters actually in .net core projects, similar to this ticket. So you can't use Azure Active Directory Authentication like this, and it's not recommended to use AAD Authentication for REST services in SOAP service.
As a workaround you can try windows Authentication:
VssConnection connection = new VssConnection(new Uri("http://instanceName:8080/tfs/OrgName/"), new WindowsCredential(new NetworkCredential("xxx", "xxx")));

Related

Blazor throwing error when using HttpContext

I want to get current windows user name when user opens the website. My application uses Blazor server-side. To get current username, I added:
In startup.cs:
services.AddHttpContextAccessor(); (under
ConfigureServices)
In razor page:
#inject IHttpContextAccessor httpContextAccessor
In razor page method:
string userName = httpContextAccessor.HttpContext.User.Identity.Name;
When I execute the code, the application throws an exception:
"An error has occurred. This application may no longer respond until reloaded."
I get this error only when I deploy on IIS. On local machine it works well.
I had a similar issue trying to access HttpContext for user information using Blazor. I found this here which was a life saver. HttpContext is NULL when running web app in IIS
All I had to do to solve the problem was to enable WebSockets in IIS.
Here are the steps: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-3.1#iisiis-express-support
If you were to change that string from
string userName = httpContextAccessor.HttpContext.User.Identity.Name
to
string userName = httpContextAccessor?.HttpContext?.User?.Identity?.Name??"Anonymous"
then it would probably work.
It's because your IIS settings are allowing anonymous access and so your Identity object is null.
You should check for the inner exceptions behind the application crash but that will be your issue. You need to prevent anonymous access on IIS to get the Windows authentication passed through.
To manage IIS refer here https://stackoverflow.com/a/5458963/12285843

System.TypeInitializationException: The type initializer for 'Microsoft.IdentityModel.Clients.ActiveDirectory.Authenticator' threw an exception

I'm attempting to perform S2S authentication from a Dynamics 365 plugin, unsuccessfully so far. The following exception occurs:
System.TypeInitializationException: The type initializer for 'Microsoft.IdentityModel.Clients.ActiveDirectory.Authenticator' threw an exception
My understanding is that the exception is thrown at the time when IdentityModel dll gets loaded, not even during runtime. However, if that matters, here is what we are doing in code:
var clientCreds = new ClientCredential(clientId, secret);
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
AuthenticationResult authResult = authContext.AcquireTokenAsync(resource, clientCreds).GetAwaiter().GetResult();
We are using the following packages:
The same code works in a console app. Any help/suggestions are very appreciated.
This might be because you are running in the sandbox. Whilst the MSDN doesn't explicity advise against this, it recommends you only connect to anonymous services.
Plug-in isolation, trusts, and statistics
Access to the file system, system event log, certain network protocols, registry, and more is prevented in the sandbox.
...
Sandboxed plug-ins and custom workflow activities can access the
network through the HTTP and HTTPS protocols....The following web
access restrictions apply to this sandbox capability.
Anonymous authentication is supported and recommended.

401 Unauthorized while ExchangeService.SubscribeToPushNotifications

Hi I have written an standalone Windows Forms application which uses EWS (Exchange Web Services) Managed API to listen to the new mail event on a particular email id. I am using impersonation. This is a part of my code:
service = new ExchangeService(SyncSettings.ExchangeServerVersion);
service.Credentials = new WebCredentials(userid, password);
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, impersonatedUserId);
service.Url = new Uri(exchnguri);
FolderId[] folders=new FolderId[1];
folders[0] = new FolderId(WellKnownFolderName.Inbox);
EventType[] events = new EventType[1];
events[0] = EventType.NewMail;
subscription = service.SubscribeToPushNotifications(folders, new Uri(listenUri), notificationInterval, "", events);
On Exchange Server side, I have provided one user account privileges to impersonate another user account.
When I run app in one environment it works fine. But when I run it in another it gives following error:
Immediate Stack Trace
===================================================================================
Microsoft.Exchange.WebServices.Data.ServiceRequestException : The request failed. The remote server returned an error: (401) Unauthorized.
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request)
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(IEwsHttpWebRequest& request)
at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute()
at Microsoft.Exchange.WebServices.Data.ExchangeService.SubscribeToPushNotifications(IEnumerable`1 folderIds, Uri url, Int32 frequency, String watermark, EventType[] eventTypes)
at com.org.app.Class.startListeningPushNotifications(String listenUri, Int32 notificationInterval) in c:\SW\app\Class.cs:line 156
Inner Exception 1 : Stack Trace
-----------------------------------------------------------------------------
System.Net.WebException . The remote server returned an error: (401) Unauthorized.
at System.Net.HttpWebRequest.GetResponse()
at Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.Microsoft.Exchange.WebServices.Data.IEwsHttpWebRequest.GetResponse()
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request)
The only difference I observe in two environments is:
In first environment I login owa (Outlook Web Access) using domainx\userx, and to send mail to self account (that is, to the account with which I have logged in) I put userx#domainx.com in to field
However in second environment I login owa using domainxdc\userx (notice 'dc' in domainxdc), and send self mail with userx#domainx.com in to field. (notice no 'dc' in domainx.com)
I dont think that is giving me 401 Unauthorised, since I can login to owa using both impersonating and impersonated account. And I have given impersonating privileges in 2nd environment in exactly the same way as in 1st environment.
So why I am getting 401 Unauthorised ?
We are using Exchange Server 2007 and Windows Server 2008 SP2.
Here's something to try--might work:
service.CookieContainer = new CookieContainer();
I'm not very clear on why this helps, and in my case, it was going against Exchange Online, not your on-prem E2007. Might help; can't hurt. There was a blog post on this, but not sure if this will apply to your case.

Reflection, WCF Web service, LoadFrom Assembly oh my. Issues with Network Credentials

I've created a WCF webservice, that can dynamically call other webservices/db connections with DLL's loaded with .LoadFile('from assembly'). Inside one of these assemblies, another webservice is called dynamically with a passed in network credential as follows:
WebClient client = new WebClient();
client.Credentials = this.networkCredential; //This credential is passed in
RequestStream requestStream = client.OpenRead(this.url);
//rest of code. The .OpenRead is giving 401 error (not authorized).
When I do this in debug mode from a test console application and creating the network credentials as follows:
NetworkCredential networkCredential = new NetworkCredential(<userid>,<password>,<domain>);
this works fine.
The failing code is providing networkcredentials as follows
System.Net.NetworkCredential networkCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
Any help would be greatly appreciated.
Unless you are using impersonation, DefaultNetworkCredentials attempts to use the credentials of the process running your ASP.NET website, not the credentials of the user accessing your site. In order to use the credentials of the user, you should wrap your call to the web services in an impersonation context.
var impersonationContext = HttpContext.Current.Request.User.Identity.Impersonate();
if(impersonationContext != null)
{
//call your webservice here. DefaultNetworkCredentials will be what you expect.
impersonationContext.Undo();
}
There are, of course, conditions. The user must be authenticated (can't be an anonymous user, unless the anonymous user also has access to your web service). Also, the code above is just an example - in production code there are quite a few other things to consider. Here is an msdn article that should help get you started.
FYI, the reason it works in development is most likely because your development server process runs as you, and since you have access to the web service, it succeeds.

How to access a site running with a different applicatio pool account

I have a piece of code executing inside a SPWeb, which has to create a SPSIte and SPWeb objects of sites in a different Web Application runing with a different application pool account. I am getting an error like this:
Error: An exception has occurred. ExceptionType: 'SqlException' ExceptionMessage: 'Cannot open database "WSS_Content_Team_Standard_01" requested by the login. The login failed. Login failed for user 'IINET\UATSP_MyAppool Acc'.' '
How do i achieve this?
Thanks in advance :)
This is because the app pool account for the context web app does not have permissions to the content db of the "remote" SPSite. This is actually a good thing from a security perspective.
One way to work around this problem is to call a (custom) webservice or HTTP Handler hosted by the remote SPSite which does the actual work that requires access to the content db.
I personally would not try to go down the route of windows impersonation or changing db permissions.
This can be done by creating new SPSite Object from the given Site Collection and passing Web App pool user token as parameter for it.The new SPSite object should be under seperate SPSecurity.RunWithElevatedPrevileges