DevOps : Non-Interactive login in new DevOps(VSTS) not working getting error 'TF30063: You are not authorized to access - azure-devops

I am trying to connect to Azure DevOps previously known as VSTS using c#. I want to connect to it without the login screen of azure DevOps. I am currently trying the following code but some how it is not working
NetworkCredential netCred = new NetworkCredential("test#hotmail.com", "test");
Uri tfsuri = new Uri("https://dev.azure.com/test10");
VssBasicCredential bsCred = new VssBasicCredential(netCred);
VssCredentials vssCred = new VssClientCredentials(bsCred);
TfsTeamProjectCollection collection = new TfsTeamProjectCollection(tfsuri, vssCred);
collection.Authenticate();
var witClient = collection.GetClient<ProjectHttpClient>();
var listOfProjects = witClient.GetProjects().Result;
libraries I am using
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.Operations;
using Microsoft.VisualStudio.Services.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
The code prompts a login screen, on which if I enter the password the auth still does not work. I dont want the login screen to appear and only want to connect with the username and password.
With alternate credentials this method is working but it is not my requirement and I can not use alternate credentials.
I have tried following the samples from the official site but no solution is working for the new DevOps.
Any Solution how can I authenticate with usernanme/password in the new DevOps without the login screen

The class TfsTeamProjectCollection is from the old .Net libraries, try the new Azure DevOps .Net libraries, and you can authenticate in a few ways:
NTLM
The most basic one is constructing a VssCredentials instance with no parameter at all and what you’ll be using is simply put integrated authentication / NTLM:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssCredentials());
Basic Authentication
VSTS and TFS also provide means to utilize Basic authentication (HTTP AUTH) which you need to create and enable first (see VSTS guidelines) and once you’ve done so, you can use them via the API like this:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssBasicCredential(username, password));
Personal Access Tokens
Next up are Personal Access Tokens (PAT) which you can easily create following the VSTS guidelines and those PATs are a means of authenticating separately from your actual credentials with a fine-grained & per access token scopes of security. Simply put it allows you to create a PAT for every use-case or even application and thereby enabling a secure and clearly separated way of giving an application or 3rd party access to your VSTS or TFS system on your behalf.
To use these via the API, you use the exact same mechanism as via Basic Authentication but you simply don’t provide any username (well – an empty one to be precise), and the PAT itself is used as the password:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssBasicCredential(string.Empty, pat));
Visual Studio Sign-in Prompt
Moreover, another way of authenticating is using the standard VS Sign-In prompt which is similarly easy and exposed via the VssClientCredentials class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssClientCredentials());
OAuth Authentication
OAuth is a widely used but a slightly more tedious authorization protocol to implement but luckily there’s a thorough sample application available at CodePlex specifically for VSTS / VSO (which also works for on-premises).
Once you have the corresponding access token, you can use it to VSTS / TFS utilizing the VssOAuthCredential class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssOAuthCredential(accessToken));
Azure Active Directory Authentication
Last but not least you can utilize Azure Active Directory identities to authenticate against a VSTS or TFS system via the VssAadCredential class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssAadCredential(username, password));

Related

How do you use MSAL to connect to Azure DevOps from vanilla JS in browser, with no-backend or AD tenant

If I use a Personal Access Token, I can access all Azure DevOps REST APIS by including the PAT in the header. This works great from NodeJS, PowerShell and curl, but I want to do the same thing from JS running in a web-browser, without any server-side code. Just purely from the JS in the browser.
Now, I could prompt the user to enter their PAT and store it in local storage, but I'd rather not do that. Instead, I'd like to prompt the user to log in and get a token that way. Microsoft has the MSAL library to do that, and they have sample code on how to do this from JavaScript in the browser. Unfortunately, for some reason, they require that you also create an Azure AD Tenant along with a client ID. I don't want to use Azure cloud for anything. I just want my users to access an existing company Azure DevOps server. As I said I can already access these resources using a PAT that the user has to create from the portal themselves. I want to avoid that step and have them log in to get a token. Seems simple enough. Am I missing something?
Why is a tenant even needed for this?
From the doc: https://github.com/AzureAD/microsoft-authentication-library-for-java/wiki
Before using MSAL4J you will have to register your applications with
Azure AD.
In conclusion, to use MSAL to connect to Azure DevOps from vanilla JS in browser, you need to register your App with Azure AD first to acquire the client ID for authorization.

Identity Server Windows and Username Password

I have identity server 3 setup and working with Windows Authentication, I have the Identity Server instance and the Windows Auth in 2 separate projects, I store custom claims in the database so I add these claims to the token in order to not have to make Web Api use windows and have to check user claims on every request since I have a separate Javascript client that uses the service. Great all works.
How do I add other authencation options to the identity server instance other type of clients? For Windows users in the domain I want to use Windows Auth and for users outside the domain I want to be able to show the login with username password but I don't want the windows users inside the domain to see the Identity Server page with the windows button.
I'm a little confused on how to setup this line:
factory.UserService = new Registration<IUserService>(typeof(ExternalRegistrationUserService));
var options = new IdentityServerOptions
{
SigningCertificate = Certificate.Load(),
Factory = factory,
AuthenticationOptions = new AuthenticationOptions
{
EnableLocalLogin = false,
IdentityProviders = ConfigureIdentityProviders,
}
};
Do I need to seutp multiple Identity Servers or can one Instance Support Muliple AuthenticationOptions?
You don't need multiple identity servers for that. Are you using identityserver 3 or 4? IdentityServer4 has a page in the documentation explaining how to do it with WebListener or Kestrel: http://docs.identityserver.io/en/release/topics/windows.html

azure sdk for net login is takes too long

I am using Fluent Library to develop a web app which can create a sql server on azure. The console app works great but when I implement the code to a web api it stuck in authentication step. I'm sure about the credentials which are true and I have a Service Principal.
// Authenticate
var credentials = new AzureCredentials(new ServicePrincipalLoginInformation { ClientId = ClientId, ClientSecret = Password }, tenantId, AzureEnvironment.AzureGlobalCloud);
var azure = Azure.Configure().Authenticate(credentials).WithDefaultSubscription();
I also can repro it on my side. I try to debug it with following code and add quick watch for azureauth.WithDefaultSubscription(), then get value The function evaluation requires all threads to run. So I guess that it may run some threads that WebAPI can't handle.
var azureauth = Azure.Configure().Authenticate(credentials);
azureauth.WithDefaultSubscription()
Please have a try to use following code to use specified subscriptionId as workaround. It works correctly on my side.
var azure = Azure.Configure().Authenticate(credentials).WithSubscription("subscriptionId");

TFS REST API: How to "Make requests on behalf of others"?

I want my VSTS extension (installed on-prem TFS2015.3) to be able to do specific requests on behalf of a admin/service account ("Make requests on behalf of others")
Background: I manipulate (WorkItem) Process Template, specifically the GLOBALWORKFLOW (only on team-project level) in my extensions typescript, but the user of the extension in Web Access is NOT a project-admin so he is not allowed to use the function updateWorkItemTypeDefinition() - Non-Project-Admins get "Access denied" even if I gave that custom group every permission available ("Edit project-level-information" permissions for project-level GLOBALWORKFLOWs? Still didn't work for custom groups, only for Project Admin Accounts).
It seems I'm forced to impersonate a project admin /service account which is allowed to change the global workflow in the project
How do I impersonate in extension typescript code on-prem TFS and REST (1. not .NET and 2. without changing to basic auth, saw that solution already somewhere else - but I'm very sure I cannot request that change in my organization)
Thanks for your help
You can impersonate user through vsts-node-api.
There are many function to impersonate user, such as Basic, NTLM, PWA (VSTS) etc..., you can check these function here.
import * as vm from 'vso-node-api';
// your collection url
var collectionUrl = "XXX";
let authHandler = vm.getNtlmHandler("[user name]","[password]","[workstation optional]","[domain optional]");
var connect = new vm.WebApi(collectionUrl, authHandler);
There is the sample that you could refer to.

Authenticating (Team Foundation Server) with impersonalization

I have found how to authenticate to TFS from my app with a given username/password.
I'd like to use the REST services.
public static void BasicAuthRestSample()
{
// Create instance of VssConnection using basic auth credentials.
// For security, ensure you are connecting to an https server, since credentials get sent in plain text.
VssConnection connection = new VssConnection(new Uri(collectionUri), new VssCredentials(new WindowsCredential(new NetworkCredential(username, password))));
WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>();
List<QueryHierarchyItem> items = witClient.GetQueriesAsync(teamProjectName).Result;
}
This solution is working fine, but if i create a new workitem, that is created by "username".
But i want to create workitems by impersonalized users, so i want to see "seconduser" as the creator if i look at the workitem in TFS.
I was googling a lot but can't find an example....
Update for VSTS:
After trying to implement i have found this:
"For security reasons (and compliance and a number of other reasons), the impersonation header isn't supported on Visual Studio Online"
A strange thing is that the error message currently misleading, it tells me that I need the special permission while the whole impersonation feature is actually disabled in VSTS.
According to REST API Reference for VS Team Services and TFS, there is no REST API similar to TFS Impersonation right now. As the .net api still works with VSTS for most features (not support vNext build, etc), you can take the .net api as an alternative.
You should use the TfsTeamProjectCollection constructor accepting an IdentityDescriptor.
You can find the full explanation in Introducing TFS Impersonation.
Snippet from the post
// Get the TFS Identity Management Service
IIdentityManagementService identityManagementService =
currentUserCollection.GetService<IIdentityManagementService>();
// Look up the user that we want to impersonate
TeamFoundationIdentity identity = identityManagementService.ReadIdentity(
IdentitySearchFactor.AccountName, username, MembershipQuery.None, ReadIdentityOptions.None);
TfsTeamProjectCollection impersonatedCollection =
new TfsTeamProjectCollection(currentUserCollection.Uri, identity.Descriptor);